11802d0beSThomas Gleixner// SPDX-License-Identifier: GPL-2.0-only
273d9f979SHans Verkuil/*
373d9f979SHans Verkuil * Copyright (C) 2005-2006 Micronas USA Inc.
473d9f979SHans Verkuil */
573d9f979SHans Verkuil
673d9f979SHans Verkuil#include <linux/module.h>
773d9f979SHans Verkuil#include <linux/init.h>
873d9f979SHans Verkuil#include <linux/i2c.h>
973d9f979SHans Verkuil#include <linux/videodev2.h>
1073d9f979SHans Verkuil#include <media/v4l2-device.h>
11b5dcee22SMauro Carvalho Chehab#include <media/i2c/uda1342.h>
1273d9f979SHans Verkuil#include <linux/slab.h>
1373d9f979SHans Verkuil
1473d9f979SHans Verkuilstatic int write_reg(struct i2c_client *client, int reg, int value)
1573d9f979SHans Verkuil{
1673d9f979SHans Verkuil	/* UDA1342 wants MSB first, but SMBus sends LSB first */
1773d9f979SHans Verkuil	i2c_smbus_write_word_data(client, reg, swab16(value));
1873d9f979SHans Verkuil	return 0;
1973d9f979SHans Verkuil}
2073d9f979SHans Verkuil
2173d9f979SHans Verkuilstatic int uda1342_s_routing(struct v4l2_subdev *sd,
2273d9f979SHans Verkuil		u32 input, u32 output, u32 config)
2373d9f979SHans Verkuil{
2473d9f979SHans Verkuil	struct i2c_client *client = v4l2_get_subdevdata(sd);
2573d9f979SHans Verkuil
2673d9f979SHans Verkuil	switch (input) {
2773d9f979SHans Verkuil	case UDA1342_IN1:
2873d9f979SHans Verkuil		write_reg(client, 0x00, 0x1241); /* select input 1 */
2973d9f979SHans Verkuil		break;
3073d9f979SHans Verkuil	case UDA1342_IN2:
3173d9f979SHans Verkuil		write_reg(client, 0x00, 0x1441); /* select input 2 */
3273d9f979SHans Verkuil		break;
3373d9f979SHans Verkuil	default:
3473d9f979SHans Verkuil		v4l2_err(sd, "input %d not supported\n", input);
3573d9f979SHans Verkuil		break;
3673d9f979SHans Verkuil	}
3773d9f979SHans Verkuil	return 0;
3873d9f979SHans Verkuil}
3973d9f979SHans Verkuil
4073d9f979SHans Verkuilstatic const struct v4l2_subdev_audio_ops uda1342_audio_ops = {
4173d9f979SHans Verkuil	.s_routing = uda1342_s_routing,
4273d9f979SHans Verkuil};
4373d9f979SHans Verkuil
4473d9f979SHans Verkuilstatic const struct v4l2_subdev_ops uda1342_ops = {
4573d9f979SHans Verkuil	.audio = &uda1342_audio_ops,
4673d9f979SHans Verkuil};
4773d9f979SHans Verkuil
4873d9f979SHans Verkuilstatic int uda1342_probe(struct i2c_client *client,
4973d9f979SHans Verkuil			     const struct i2c_device_id *id)
5073d9f979SHans Verkuil{
5173d9f979SHans Verkuil	struct i2c_adapter *adapter = client->adapter;
5273d9f979SHans Verkuil	struct v4l2_subdev *sd;
5373d9f979SHans Verkuil
5473d9f979SHans Verkuil	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
5573d9f979SHans Verkuil		return -ENODEV;
5673d9f979SHans Verkuil
5773d9f979SHans Verkuil	dev_dbg(&client->dev, "initializing UDA1342 at address %d on %s\n",
5873d9f979SHans Verkuil		client->addr, adapter->name);
5973d9f979SHans Verkuil
60c02b211dSLaurent Pinchart	sd = devm_kzalloc(&client->dev, sizeof(*sd), GFP_KERNEL);
6173d9f979SHans Verkuil	if (sd == NULL)
6273d9f979SHans Verkuil		return -ENOMEM;
6373d9f979SHans Verkuil
6473d9f979SHans Verkuil	v4l2_i2c_subdev_init(sd, client, &uda1342_ops);
6573d9f979SHans Verkuil
6673d9f979SHans Verkuil	write_reg(client, 0x00, 0x8000); /* reset registers */
6773d9f979SHans Verkuil	write_reg(client, 0x00, 0x1241); /* select input 1 */
6873d9f979SHans Verkuil
6973d9f979SHans Verkuil	v4l_info(client, "chip found @ 0x%02x (%s)\n",
7073d9f979SHans Verkuil			client->addr << 1, client->adapter->name);
7173d9f979SHans Verkuil
7273d9f979SHans Verkuil	return 0;
7373d9f979SHans Verkuil}
7473d9f979SHans Verkuil
7573d9f979SHans Verkuilstatic int uda1342_remove(struct i2c_client *client)
7673d9f979SHans Verkuil{
7773d9f979SHans Verkuil	struct v4l2_subdev *sd = i2c_get_clientdata(client);
7873d9f979SHans Verkuil
7973d9f979SHans Verkuil	v4l2_device_unregister_subdev(sd);
8073d9f979SHans Verkuil	return 0;
8173d9f979SHans Verkuil}
8273d9f979SHans Verkuil
8373d9f979SHans Verkuilstatic const struct i2c_device_id uda1342_id[] = {
8473d9f979SHans Verkuil	{ "uda1342", 0 },
8573d9f979SHans Verkuil	{ }
8673d9f979SHans Verkuil};
8773d9f979SHans VerkuilMODULE_DEVICE_TABLE(i2c, uda1342_id);
8873d9f979SHans Verkuil
8973d9f979SHans Verkuilstatic struct i2c_driver uda1342_driver = {
9073d9f979SHans Verkuil	.driver = {
9173d9f979SHans Verkuil		.name	= "uda1342",
9273d9f979SHans Verkuil	},
9373d9f979SHans Verkuil	.probe		= uda1342_probe,
9473d9f979SHans Verkuil	.remove		= uda1342_remove,
9573d9f979SHans Verkuil	.id_table	= uda1342_id,
9673d9f979SHans Verkuil};
9773d9f979SHans Verkuil
9873d9f979SHans Verkuilmodule_i2c_driver(uda1342_driver);
9973d9f979SHans Verkuil
10073d9f979SHans VerkuilMODULE_LICENSE("GPL v2");
101