xref: /openbmc/linux/drivers/media/i2c/bt856.c (revision 078b39c9)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * bt856 - BT856A Digital Video Encoder (Rockwell Part)
4  *
5  * Copyright (C) 1999 Mike Bernson <mike@mlb.org>
6  * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
7  *
8  * Modifications for LML33/DC10plus unified driver
9  * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
10  *
11  * This code was modify/ported from the saa7111 driver written
12  * by Dave Perks.
13  *
14  * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
15  *   - moved over to linux>=2.4.x i2c protocol (9/9/2002)
16  */
17 
18 #include <linux/module.h>
19 #include <linux/types.h>
20 #include <linux/slab.h>
21 #include <linux/ioctl.h>
22 #include <linux/uaccess.h>
23 #include <linux/i2c.h>
24 #include <linux/videodev2.h>
25 #include <media/v4l2-device.h>
26 
27 MODULE_DESCRIPTION("Brooktree-856A video encoder driver");
28 MODULE_AUTHOR("Mike Bernson & Dave Perks");
29 MODULE_LICENSE("GPL");
30 
31 static int debug;
32 module_param(debug, int, 0);
33 MODULE_PARM_DESC(debug, "Debug level (0-1)");
34 
35 
36 /* ----------------------------------------------------------------------- */
37 
38 #define BT856_REG_OFFSET	0xDA
39 #define BT856_NR_REG		6
40 
41 struct bt856 {
42 	struct v4l2_subdev sd;
43 	unsigned char reg[BT856_NR_REG];
44 
45 	v4l2_std_id norm;
46 };
47 
48 static inline struct bt856 *to_bt856(struct v4l2_subdev *sd)
49 {
50 	return container_of(sd, struct bt856, sd);
51 }
52 
53 /* ----------------------------------------------------------------------- */
54 
55 static inline int bt856_write(struct bt856 *encoder, u8 reg, u8 value)
56 {
57 	struct i2c_client *client = v4l2_get_subdevdata(&encoder->sd);
58 
59 	encoder->reg[reg - BT856_REG_OFFSET] = value;
60 	return i2c_smbus_write_byte_data(client, reg, value);
61 }
62 
63 static inline int bt856_setbit(struct bt856 *encoder, u8 reg, u8 bit, u8 value)
64 {
65 	return bt856_write(encoder, reg,
66 		(encoder->reg[reg - BT856_REG_OFFSET] & ~(1 << bit)) |
67 				(value ? (1 << bit) : 0));
68 }
69 
70 static void bt856_dump(struct bt856 *encoder)
71 {
72 	int i;
73 
74 	v4l2_info(&encoder->sd, "register dump:\n");
75 	for (i = 0; i < BT856_NR_REG; i += 2)
76 		printk(KERN_CONT " %02x", encoder->reg[i]);
77 	printk(KERN_CONT "\n");
78 }
79 
80 /* ----------------------------------------------------------------------- */
81 
82 static int bt856_init(struct v4l2_subdev *sd, u32 arg)
83 {
84 	struct bt856 *encoder = to_bt856(sd);
85 
86 	/* This is just for testing!!! */
87 	v4l2_dbg(1, debug, sd, "init\n");
88 	bt856_write(encoder, 0xdc, 0x18);
89 	bt856_write(encoder, 0xda, 0);
90 	bt856_write(encoder, 0xde, 0);
91 
92 	bt856_setbit(encoder, 0xdc, 3, 1);
93 	/*bt856_setbit(encoder, 0xdc, 6, 0);*/
94 	bt856_setbit(encoder, 0xdc, 4, 1);
95 
96 	if (encoder->norm & V4L2_STD_NTSC)
97 		bt856_setbit(encoder, 0xdc, 2, 0);
98 	else
99 		bt856_setbit(encoder, 0xdc, 2, 1);
100 
101 	bt856_setbit(encoder, 0xdc, 1, 1);
102 	bt856_setbit(encoder, 0xde, 4, 0);
103 	bt856_setbit(encoder, 0xde, 3, 1);
104 	if (debug != 0)
105 		bt856_dump(encoder);
106 	return 0;
107 }
108 
109 static int bt856_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
110 {
111 	struct bt856 *encoder = to_bt856(sd);
112 
113 	v4l2_dbg(1, debug, sd, "set norm %llx\n", (unsigned long long)std);
114 
115 	if (std & V4L2_STD_NTSC) {
116 		bt856_setbit(encoder, 0xdc, 2, 0);
117 	} else if (std & V4L2_STD_PAL) {
118 		bt856_setbit(encoder, 0xdc, 2, 1);
119 		bt856_setbit(encoder, 0xda, 0, 0);
120 		/*bt856_setbit(encoder, 0xda, 0, 1);*/
121 	} else {
122 		return -EINVAL;
123 	}
124 	encoder->norm = std;
125 	if (debug != 0)
126 		bt856_dump(encoder);
127 	return 0;
128 }
129 
130 static int bt856_s_routing(struct v4l2_subdev *sd,
131 			   u32 input, u32 output, u32 config)
132 {
133 	struct bt856 *encoder = to_bt856(sd);
134 
135 	v4l2_dbg(1, debug, sd, "set input %d\n", input);
136 
137 	/* We only have video bus.
138 	 * input= 0: input is from bt819
139 	 * input= 1: input is from ZR36060 */
140 	switch (input) {
141 	case 0:
142 		bt856_setbit(encoder, 0xde, 4, 0);
143 		bt856_setbit(encoder, 0xde, 3, 1);
144 		bt856_setbit(encoder, 0xdc, 3, 1);
145 		bt856_setbit(encoder, 0xdc, 6, 0);
146 		break;
147 	case 1:
148 		bt856_setbit(encoder, 0xde, 4, 0);
149 		bt856_setbit(encoder, 0xde, 3, 1);
150 		bt856_setbit(encoder, 0xdc, 3, 1);
151 		bt856_setbit(encoder, 0xdc, 6, 1);
152 		break;
153 	case 2:	/* Color bar */
154 		bt856_setbit(encoder, 0xdc, 3, 0);
155 		bt856_setbit(encoder, 0xde, 4, 1);
156 		break;
157 	default:
158 		return -EINVAL;
159 	}
160 
161 	if (debug != 0)
162 		bt856_dump(encoder);
163 	return 0;
164 }
165 
166 /* ----------------------------------------------------------------------- */
167 
168 static const struct v4l2_subdev_core_ops bt856_core_ops = {
169 	.init = bt856_init,
170 };
171 
172 static const struct v4l2_subdev_video_ops bt856_video_ops = {
173 	.s_std_output = bt856_s_std_output,
174 	.s_routing = bt856_s_routing,
175 };
176 
177 static const struct v4l2_subdev_ops bt856_ops = {
178 	.core = &bt856_core_ops,
179 	.video = &bt856_video_ops,
180 };
181 
182 /* ----------------------------------------------------------------------- */
183 
184 static int bt856_probe(struct i2c_client *client)
185 {
186 	struct bt856 *encoder;
187 	struct v4l2_subdev *sd;
188 
189 	/* Check if the adapter supports the needed features */
190 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
191 		return -ENODEV;
192 
193 	v4l_info(client, "chip found @ 0x%x (%s)\n",
194 			client->addr << 1, client->adapter->name);
195 
196 	encoder = devm_kzalloc(&client->dev, sizeof(*encoder), GFP_KERNEL);
197 	if (encoder == NULL)
198 		return -ENOMEM;
199 	sd = &encoder->sd;
200 	v4l2_i2c_subdev_init(sd, client, &bt856_ops);
201 	encoder->norm = V4L2_STD_NTSC;
202 
203 	bt856_write(encoder, 0xdc, 0x18);
204 	bt856_write(encoder, 0xda, 0);
205 	bt856_write(encoder, 0xde, 0);
206 
207 	bt856_setbit(encoder, 0xdc, 3, 1);
208 	/*bt856_setbit(encoder, 0xdc, 6, 0);*/
209 	bt856_setbit(encoder, 0xdc, 4, 1);
210 
211 	if (encoder->norm & V4L2_STD_NTSC)
212 		bt856_setbit(encoder, 0xdc, 2, 0);
213 	else
214 		bt856_setbit(encoder, 0xdc, 2, 1);
215 
216 	bt856_setbit(encoder, 0xdc, 1, 1);
217 	bt856_setbit(encoder, 0xde, 4, 0);
218 	bt856_setbit(encoder, 0xde, 3, 1);
219 
220 	if (debug != 0)
221 		bt856_dump(encoder);
222 	return 0;
223 }
224 
225 static void bt856_remove(struct i2c_client *client)
226 {
227 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
228 
229 	v4l2_device_unregister_subdev(sd);
230 }
231 
232 static const struct i2c_device_id bt856_id[] = {
233 	{ "bt856", 0 },
234 	{ }
235 };
236 MODULE_DEVICE_TABLE(i2c, bt856_id);
237 
238 static struct i2c_driver bt856_driver = {
239 	.driver = {
240 		.name	= "bt856",
241 	},
242 	.probe		= bt856_probe,
243 	.remove		= bt856_remove,
244 	.id_table	= bt856_id,
245 };
246 
247 module_i2c_driver(bt856_driver);
248