drivers/media/i2c/tda9840.c

Source file repositories/reference/linux-study-clean/drivers/media/i2c/tda9840.c

File Facts

System
Linux kernel
Corpus path
drivers/media/i2c/tda9840.c
Extension
.c
Size
4852 bytes
Lines
200
Domain
Driver Families
Bucket
drivers/media
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

switch (t->audmode) {
		case V4L2_TUNER_MODE_LANG1_LANG2:
			byte = TDA9840_SET_BOTH;
			break;
		case V4L2_TUNER_MODE_LANG2:
			byte = TDA9840_SET_LANG2;
			break;
		default:
			byte = TDA9840_SET_LANG1;
			break;
		}
	}
	v4l2_dbg(1, debug, sd, "TDA9840_SWITCH: 0x%02x\n", byte);
	tda9840_write(sd, SWITCH, byte);
	return 0;
}

static int tda9840_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *t)
{
	int stat = tda9840_status(sd);

	if (stat < 0)
		return stat;

	t->rxsubchans = V4L2_TUNER_SUB_MONO;

	switch (stat & 0x60) {
	case 0x00:
		t->rxsubchans = V4L2_TUNER_SUB_MONO;
		break;
	case 0x20:
		t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
		break;
	case 0x40:
		t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
		break;
	default: /* Incorrect detect */
		t->rxsubchans = V4L2_TUNER_MODE_MONO;
		break;
	}
	return 0;
}

/* ----------------------------------------------------------------------- */

static const struct v4l2_subdev_tuner_ops tda9840_tuner_ops = {
	.s_tuner = tda9840_s_tuner,
	.g_tuner = tda9840_g_tuner,
};

static const struct v4l2_subdev_ops tda9840_ops = {
	.tuner = &tda9840_tuner_ops,
};

/* ----------------------------------------------------------------------- */

static int tda9840_probe(struct i2c_client *client)
{
	struct v4l2_subdev *sd;

	/* let's see whether this adapter can support what we need */
	if (!i2c_check_functionality(client->adapter,
			I2C_FUNC_SMBUS_READ_BYTE_DATA |
			I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
		return -EIO;

	v4l_info(client, "chip found @ 0x%x (%s)\n",
			client->addr << 1, client->adapter->name);

	sd = devm_kzalloc(&client->dev, sizeof(*sd), GFP_KERNEL);
	if (sd == NULL)
		return -ENOMEM;
	v4l2_i2c_subdev_init(sd, client, &tda9840_ops);

	/* set initial values for level & stereo - adjustment, mode */
	tda9840_write(sd, LEVEL_ADJUST, 0);
	tda9840_write(sd, STEREO_ADJUST, 0);
	tda9840_write(sd, SWITCH, TDA9840_SET_STEREO);
	return 0;
}

static void tda9840_remove(struct i2c_client *client)
{
	struct v4l2_subdev *sd = i2c_get_clientdata(client);

	v4l2_device_unregister_subdev(sd);
}

static const struct i2c_device_id tda9840_id[] = {
	{ .name = "tda9840" },

Annotation

Implementation Notes