Commit e090901e authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

[media] saa7115: move the autodetection code out of the probe function

As we're now seeing other variants from chinese clones, like
gm1113c, we'll need to add more bits at the detection code.
So, move it into a separate function.
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
Tested-by: default avatarJon Arne Jørgensen <jonarne@jonarne.no>
Tested-by: default avatarEzequiel Garcia <ezequiel.garcia@free-electrons.com>
Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 5255e4d9
...@@ -1573,46 +1573,103 @@ static const struct v4l2_subdev_ops saa711x_ops = { ...@@ -1573,46 +1573,103 @@ static const struct v4l2_subdev_ops saa711x_ops = {
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
static int saa711x_probe(struct i2c_client *client, /**
const struct i2c_device_id *id) * saa711x_detect_chip - Detects the saa711x (or clone) variant
* @client: I2C client structure.
* @id: I2C device ID structure.
* @name: Name of the device to be filled.
* @size: Size of the name var.
*
* Detects the Philips/NXP saa711x chip, or some clone of it.
* if 'id' is NULL or id->driver_data is equal to 1, it auto-probes
* the analog demod.
* If the tuner is not found, it returns -ENODEV.
* If auto-detection is disabled and the tuner doesn't match what it was
* requred, it returns -EINVAL and fills 'name'.
* If the chip is found, it returns the chip ID and fills 'name'.
*/
static int saa711x_detect_chip(struct i2c_client *client,
const struct i2c_device_id *id,
char *name, unsigned size)
{ {
struct saa711x_state *state; char chip_ver[size - 1];
struct v4l2_subdev *sd;
struct v4l2_ctrl_handler *hdl;
int i;
char name[17];
char chip_id; char chip_id;
int autodetect = !id || id->driver_data == 1; int i;
int autodetect;
/* Check if the adapter supports the needed features */ autodetect = !id || id->driver_data == 1;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -EIO;
for (i = 0; i < 0x0f; i++) { /* Read the chip version register */
for (i = 0; i < size - 1; i++) {
i2c_smbus_write_byte_data(client, 0, i); i2c_smbus_write_byte_data(client, 0, i);
name[i] = (i2c_smbus_read_byte_data(client, 0) & 0x0f) + '0'; chip_ver[i] = i2c_smbus_read_byte_data(client, 0);
name[i] = (chip_ver[i] & 0x0f) + '0';
if (name[i] > '9') if (name[i] > '9')
name[i] += 'a' - '9' - 1; name[i] += 'a' - '9' - 1;
} }
name[i] = '\0'; name[i] = '\0';
/* Check if it is a Philips/NXP chip */
if (!memcmp(name + 1, "f711", 4)) {
chip_id = name[5]; chip_id = name[5];
snprintf(name, size, "saa711%c", chip_id);
/* Check whether this chip is part of the saa711x series */ if (!autodetect && strcmp(name, id->name))
if (memcmp(name + 1, "f711", 4)) { return -EINVAL;
v4l_dbg(1, debug, client, "chip found @ 0x%x (ID %s) does not match a known saa711x chip.\n",
client->addr << 1, name); switch (chip_id) {
return -ENODEV; case '1':
if (chip_ver[0] & 0xf0) {
snprintf(name, size, "saa711%ca", chip_id);
v4l_info(client, "saa7111a variant found\n");
return V4L2_IDENT_SAA7111A;
}
return V4L2_IDENT_SAA7111;
case '3':
return V4L2_IDENT_SAA7113;
case '4':
return V4L2_IDENT_SAA7114;
case '5':
return V4L2_IDENT_SAA7115;
case '8':
return V4L2_IDENT_SAA7118;
default:
v4l2_info(client,
"WARNING: Philips/NXP chip unknown - Falling back to saa7111\n");
return V4L2_IDENT_SAA7111;
}
} }
/* Safety check */ /* Chip was not discovered. Return its ID and don't bind */
if (!autodetect && id->name[6] != chip_id) { v4l_dbg(1, debug, client, "chip %*ph @ 0x%x is unknown.\n",
v4l_warn(client, "found saa711%c while %s was expected\n", 16, chip_ver, client->addr << 1);
chip_id, id->name); return -ENODEV;
}
static int saa711x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct saa711x_state *state;
struct v4l2_subdev *sd;
struct v4l2_ctrl_handler *hdl;
int ident;
char name[17];
/* Check if the adapter supports the needed features */
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -EIO;
ident = saa711x_detect_chip(client, id, name, sizeof(name));
if (ident == -EINVAL) {
/* Chip exists, but doesn't match */
v4l_warn(client, "found %s while %s was expected\n",
name, id->name);
return -ENODEV;
} }
snprintf(client->name, sizeof(client->name), "saa711%c", chip_id); if (ident < 0)
v4l_info(client, "saa711%c found (%s) @ 0x%x (%s)\n", chip_id, name, return ident;
client->addr << 1, client->adapter->name);
strlcpy(client->name, name, sizeof(client->name));
state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
if (state == NULL) if (state == NULL)
...@@ -1648,31 +1705,7 @@ static int saa711x_probe(struct i2c_client *client, ...@@ -1648,31 +1705,7 @@ static int saa711x_probe(struct i2c_client *client,
state->output = SAA7115_IPORT_ON; state->output = SAA7115_IPORT_ON;
state->enable = 1; state->enable = 1;
state->radio = 0; state->radio = 0;
switch (chip_id) { state->ident = ident;
case '1':
state->ident = V4L2_IDENT_SAA7111;
if (saa711x_read(sd, R_00_CHIP_VERSION) & 0xf0) {
v4l_info(client, "saa7111a variant found\n");
state->ident = V4L2_IDENT_SAA7111A;
}
break;
case '3':
state->ident = V4L2_IDENT_SAA7113;
break;
case '4':
state->ident = V4L2_IDENT_SAA7114;
break;
case '5':
state->ident = V4L2_IDENT_SAA7115;
break;
case '8':
state->ident = V4L2_IDENT_SAA7118;
break;
default:
state->ident = V4L2_IDENT_SAA7111;
v4l2_info(sd, "WARNING: Chip is not known - Falling back to saa7111\n");
break;
}
state->audclk_freq = 48000; state->audclk_freq = 48000;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment