blob: 0a1efc1417bc3da05f221606154b72b8c7b825d5 [file] [log] [blame]
Thomas Gleixnerc942fdd2019-05-27 08:55:06 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Hans Verkuil761dacd2007-10-30 05:41:25 -03002/*
3 * m52790 i2c ivtv driver.
4 * Copyright (C) 2007 Hans Verkuil
5 *
6 * A/V source switching Mitsubishi M52790SP/FP
Hans Verkuil761dacd2007-10-30 05:41:25 -03007 */
8
9
10#include <linux/module.h>
11#include <linux/types.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090012#include <linux/slab.h>
Hans Verkuil761dacd2007-10-30 05:41:25 -030013#include <linux/ioctl.h>
Linus Torvalds7c0f6ba2016-12-24 11:46:01 -080014#include <linux/uaccess.h>
Hans Verkuil761dacd2007-10-30 05:41:25 -030015#include <linux/i2c.h>
Hans Verkuil33b687c2008-07-25 05:32:50 -030016#include <linux/videodev2.h>
Mauro Carvalho Chehabb5dcee22015-11-10 12:01:44 -020017#include <media/i2c/m52790.h>
Hans Verkuil5d302f2e2008-11-29 12:51:32 -030018#include <media/v4l2-device.h>
Hans Verkuil761dacd2007-10-30 05:41:25 -030019
20MODULE_DESCRIPTION("i2c device driver for m52790 A/V switch");
21MODULE_AUTHOR("Hans Verkuil");
22MODULE_LICENSE("GPL");
23
Hans Verkuil761dacd2007-10-30 05:41:25 -030024
25struct m52790_state {
Hans Verkuil5d302f2e2008-11-29 12:51:32 -030026 struct v4l2_subdev sd;
Hans Verkuil761dacd2007-10-30 05:41:25 -030027 u16 input;
28 u16 output;
29};
30
Hans Verkuil5d302f2e2008-11-29 12:51:32 -030031static inline struct m52790_state *to_state(struct v4l2_subdev *sd)
32{
33 return container_of(sd, struct m52790_state, sd);
34}
35
Hans Verkuil761dacd2007-10-30 05:41:25 -030036/* ----------------------------------------------------------------------- */
37
Hans Verkuil5d302f2e2008-11-29 12:51:32 -030038static int m52790_write(struct v4l2_subdev *sd)
Hans Verkuil761dacd2007-10-30 05:41:25 -030039{
Hans Verkuil5d302f2e2008-11-29 12:51:32 -030040 struct m52790_state *state = to_state(sd);
41 struct i2c_client *client = v4l2_get_subdevdata(sd);
42
Hans Verkuil761dacd2007-10-30 05:41:25 -030043 u8 sw1 = (state->input | state->output) & 0xff;
44 u8 sw2 = (state->input | state->output) >> 8;
45
46 return i2c_smbus_write_byte_data(client, sw1, sw2);
47}
48
Hans Verkuil5d302f2e2008-11-29 12:51:32 -030049/* Note: audio and video are linked and cannot be switched separately.
50 So audio and video routing commands are identical for this chip.
51 In theory the video amplifier and audio modes could be handled
52 separately for the output, but that seems to be overkill right now.
53 The same holds for implementing an audio mute control, this is now
54 part of the audio output routing. The normal case is that another
55 chip takes care of the actual muting so making it part of the
56 output routing seems to be the right thing to do for now. */
Hans Verkuil5325b422009-04-02 11:26:22 -030057static int m52790_s_routing(struct v4l2_subdev *sd,
58 u32 input, u32 output, u32 config)
Hans Verkuil761dacd2007-10-30 05:41:25 -030059{
Hans Verkuil5d302f2e2008-11-29 12:51:32 -030060 struct m52790_state *state = to_state(sd);
Hans Verkuil761dacd2007-10-30 05:41:25 -030061
Hans Verkuil5325b422009-04-02 11:26:22 -030062 state->input = input;
63 state->output = output;
Hans Verkuil5d302f2e2008-11-29 12:51:32 -030064 m52790_write(sd);
Hans Verkuil761dacd2007-10-30 05:41:25 -030065 return 0;
66}
67
Hans Verkuil5d302f2e2008-11-29 12:51:32 -030068#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuilaecde8b52008-12-30 07:14:19 -030069static int m52790_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
Hans Verkuil5d302f2e2008-11-29 12:51:32 -030070{
71 struct m52790_state *state = to_state(sd);
Hans Verkuil5d302f2e2008-11-29 12:51:32 -030072
Hans Verkuil5d302f2e2008-11-29 12:51:32 -030073 if (reg->reg != 0)
74 return -EINVAL;
Hans Verkuilaecde8b52008-12-30 07:14:19 -030075 reg->size = 1;
Hans Verkuil5d302f2e2008-11-29 12:51:32 -030076 reg->val = state->input | state->output;
77 return 0;
78}
79
Hans Verkuil977ba3b12013-03-24 08:28:46 -030080static int m52790_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
Hans Verkuil5d302f2e2008-11-29 12:51:32 -030081{
82 struct m52790_state *state = to_state(sd);
Hans Verkuil5d302f2e2008-11-29 12:51:32 -030083
Hans Verkuil5d302f2e2008-11-29 12:51:32 -030084 if (reg->reg != 0)
85 return -EINVAL;
86 state->input = reg->val & 0x0303;
87 state->output = reg->val & ~0x0303;
88 m52790_write(sd);
89 return 0;
90}
91#endif
92
Hans Verkuil5d302f2e2008-11-29 12:51:32 -030093static int m52790_log_status(struct v4l2_subdev *sd)
94{
95 struct m52790_state *state = to_state(sd);
96
97 v4l2_info(sd, "Switch 1: %02x\n",
98 (state->input | state->output) & 0xff);
99 v4l2_info(sd, "Switch 2: %02x\n",
100 (state->input | state->output) >> 8);
101 return 0;
102}
103
Hans Verkuil5d302f2e2008-11-29 12:51:32 -0300104/* ----------------------------------------------------------------------- */
105
106static const struct v4l2_subdev_core_ops m52790_core_ops = {
107 .log_status = m52790_log_status,
Hans Verkuil5d302f2e2008-11-29 12:51:32 -0300108#ifdef CONFIG_VIDEO_ADV_DEBUG
109 .g_register = m52790_g_register,
110 .s_register = m52790_s_register,
111#endif
112};
113
114static const struct v4l2_subdev_audio_ops m52790_audio_ops = {
115 .s_routing = m52790_s_routing,
116};
117
118static const struct v4l2_subdev_video_ops m52790_video_ops = {
119 .s_routing = m52790_s_routing,
120};
121
122static const struct v4l2_subdev_ops m52790_ops = {
123 .core = &m52790_core_ops,
124 .audio = &m52790_audio_ops,
125 .video = &m52790_video_ops,
126};
127
Hans Verkuil761dacd2007-10-30 05:41:25 -0300128/* ----------------------------------------------------------------------- */
129
130/* i2c implementation */
131
Jean Delvared2653e92008-04-29 23:11:39 +0200132static int m52790_probe(struct i2c_client *client,
133 const struct i2c_device_id *id)
Hans Verkuil761dacd2007-10-30 05:41:25 -0300134{
135 struct m52790_state *state;
Hans Verkuil5d302f2e2008-11-29 12:51:32 -0300136 struct v4l2_subdev *sd;
Hans Verkuil761dacd2007-10-30 05:41:25 -0300137
138 /* Check if the adapter supports the needed features */
139 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
140 return -EIO;
141
Hans Verkuil761dacd2007-10-30 05:41:25 -0300142 v4l_info(client, "chip found @ 0x%x (%s)\n",
143 client->addr << 1, client->adapter->name);
144
Laurent Pinchartc02b2112013-05-02 08:29:43 -0300145 state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
Hans Verkuil761dacd2007-10-30 05:41:25 -0300146 if (state == NULL)
147 return -ENOMEM;
148
Hans Verkuil5d302f2e2008-11-29 12:51:32 -0300149 sd = &state->sd;
150 v4l2_i2c_subdev_init(sd, client, &m52790_ops);
Hans Verkuil761dacd2007-10-30 05:41:25 -0300151 state->input = M52790_IN_TUNER;
152 state->output = M52790_OUT_STEREO;
Hans Verkuil5d302f2e2008-11-29 12:51:32 -0300153 m52790_write(sd);
Hans Verkuil761dacd2007-10-30 05:41:25 -0300154 return 0;
155}
156
157static int m52790_remove(struct i2c_client *client)
158{
Hans Verkuil5d302f2e2008-11-29 12:51:32 -0300159 struct v4l2_subdev *sd = i2c_get_clientdata(client);
160
161 v4l2_device_unregister_subdev(sd);
Hans Verkuil761dacd2007-10-30 05:41:25 -0300162 return 0;
163}
164
165/* ----------------------------------------------------------------------- */
166
Jean Delvareaf294862008-05-18 20:49:40 +0200167static const struct i2c_device_id m52790_id[] = {
168 { "m52790", 0 },
169 { }
170};
171MODULE_DEVICE_TABLE(i2c, m52790_id);
172
Hans Verkuild30f60b2010-09-15 15:18:29 -0300173static struct i2c_driver m52790_driver = {
174 .driver = {
Hans Verkuild30f60b2010-09-15 15:18:29 -0300175 .name = "m52790",
176 },
177 .probe = m52790_probe,
178 .remove = m52790_remove,
179 .id_table = m52790_id,
Hans Verkuil761dacd2007-10-30 05:41:25 -0300180};
Hans Verkuild30f60b2010-09-15 15:18:29 -0300181
Axel Linc6e8d862012-02-12 06:56:32 -0300182module_i2c_driver(m52790_driver);