xref: /linux/drivers/media/i2c/cx25840/cx25840-core.c (revision c771600c6af14749609b49565ffb4cac2959710d)
1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2bd985160SHans Verkuil /* cx25840 - Conexant CX25840 audio/video decoder driver
3bd985160SHans Verkuil  *
4bd985160SHans Verkuil  * Copyright (C) 2004 Ulf Eklund
5bd985160SHans Verkuil  *
625985edcSLucas De Marchi  * Based on the saa7115 driver and on the first version of Chris Kennedy's
7bd985160SHans Verkuil  * cx25840 driver.
8bd985160SHans Verkuil  *
9bd985160SHans Verkuil  * Changes by Tyler Trafford <tatrafford@comcast.net>
10bd985160SHans Verkuil  *    - cleanup/rewrite for V4L2 API (2005)
11bd985160SHans Verkuil  *
12bd985160SHans Verkuil  * VBI support by Hans Verkuil <hverkuil@xs4all.nl>.
13bd985160SHans Verkuil  *
143e3bf277SChristopher Neufeld  * NTSC sliced VBI support by Christopher Neufeld <television@cneufeld.ca>
153e3bf277SChristopher Neufeld  * with additional fixes by Hans Verkuil <hverkuil@xs4all.nl>.
163e3bf277SChristopher Neufeld  *
176d897616SSteven Toth  * CX23885 support by Steven Toth <stoth@linuxtv.org>.
18f234081bSSteven Toth  *
1952fd3ddaSAndy Walls  * CX2388[578] IRQ handling, IO Pin mux configuration and other small fixes are
2052fd3ddaSAndy Walls  * Copyright (C) 2010 Andy Walls <awalls@md.metrocast.net>
2152fd3ddaSAndy Walls  *
2274900b47SSteven Toth  * CX23888 DIF support for the HVR1850
2374900b47SSteven Toth  * Copyright (C) 2011 Steven Toth <stoth@kernellabs.com>
2474900b47SSteven Toth  *
25e81a9076SMaciej S. Szmigiero  * CX2584x pin to pad mapping and output format configuration support are
26e81a9076SMaciej S. Szmigiero  * Copyright (C) 2011 Maciej S. Szmigiero <mail@maciej.szmigiero.name>
27bd985160SHans Verkuil  */
28bd985160SHans Verkuil 
29bd985160SHans Verkuil #include <linux/kernel.h>
30bd985160SHans Verkuil #include <linux/module.h>
31bd985160SHans Verkuil #include <linux/slab.h>
32bd985160SHans Verkuil #include <linux/videodev2.h>
33bd985160SHans Verkuil #include <linux/i2c.h>
34f61b48f7SMichael Krufky #include <linux/delay.h>
353308e2b5SMauro Carvalho Chehab #include <linux/math64.h>
36bd985160SHans Verkuil #include <media/v4l2-common.h>
37d647f0b7SMauro Carvalho Chehab #include <media/drv-intf/cx25840.h>
38bd985160SHans Verkuil 
3931bc09b5SHans Verkuil #include "cx25840-core.h"
40bd985160SHans Verkuil 
41bd985160SHans Verkuil MODULE_DESCRIPTION("Conexant CX25840 audio/video decoder driver");
421f4b3365SHans Verkuil MODULE_AUTHOR("Ulf Eklund, Chris Kennedy, Hans Verkuil, Tyler Trafford");
43bd985160SHans Verkuil MODULE_LICENSE("GPL");
44bd985160SHans Verkuil 
4552fd3ddaSAndy Walls #define CX25840_VID_INT_STAT_REG 0x410
4652fd3ddaSAndy Walls #define CX25840_VID_INT_STAT_BITS 0x0000ffff
4752fd3ddaSAndy Walls #define CX25840_VID_INT_MASK_BITS 0xffff0000
4852fd3ddaSAndy Walls #define CX25840_VID_INT_MASK_SHFT 16
4952fd3ddaSAndy Walls #define CX25840_VID_INT_MASK_REG 0x412
5052fd3ddaSAndy Walls 
5152fd3ddaSAndy Walls #define CX23885_AUD_MC_INT_MASK_REG 0x80c
5252fd3ddaSAndy Walls #define CX23885_AUD_MC_INT_STAT_BITS 0xffff0000
5352fd3ddaSAndy Walls #define CX23885_AUD_MC_INT_CTRL_BITS 0x0000ffff
5452fd3ddaSAndy Walls #define CX23885_AUD_MC_INT_STAT_SHFT 16
5552fd3ddaSAndy Walls 
5652fd3ddaSAndy Walls #define CX25840_AUD_INT_CTRL_REG 0x812
5752fd3ddaSAndy Walls #define CX25840_AUD_INT_STAT_REG 0x813
5852fd3ddaSAndy Walls 
5952fd3ddaSAndy Walls #define CX23885_PIN_CTRL_IRQ_REG 0x123
6052fd3ddaSAndy Walls #define CX23885_PIN_CTRL_IRQ_IR_STAT  0x40
6152fd3ddaSAndy Walls #define CX23885_PIN_CTRL_IRQ_AUD_STAT 0x20
6252fd3ddaSAndy Walls #define CX23885_PIN_CTRL_IRQ_VID_STAT 0x10
6352fd3ddaSAndy Walls 
6452fd3ddaSAndy Walls #define CX25840_IR_STATS_REG	0x210
6552fd3ddaSAndy Walls #define CX25840_IR_IRQEN_REG	0x214
6652fd3ddaSAndy Walls 
67fe0d3dffSAdrian Bunk static int cx25840_debug;
68bd985160SHans Verkuil 
69b5fc7144SHans Verkuil module_param_named(debug, cx25840_debug, int, 0644);
70bd985160SHans Verkuil 
71fac9e899SHans Verkuil MODULE_PARM_DESC(debug, "Debugging messages [0=Off (default) 1=On]");
72bd985160SHans Verkuil 
73bd985160SHans Verkuil /* ----------------------------------------------------------------------- */
74ba50e7e1SDevin Heitmueller static void cx23888_std_setup(struct i2c_client *client);
75bd985160SHans Verkuil 
cx25840_write(struct i2c_client * client,u16 addr,u8 value)76bd985160SHans Verkuil int cx25840_write(struct i2c_client *client, u16 addr, u8 value)
77bd985160SHans Verkuil {
78bd985160SHans Verkuil 	u8 buffer[3];
7910a34367SMauro Carvalho Chehab 
80bd985160SHans Verkuil 	buffer[0] = addr >> 8;
81bd985160SHans Verkuil 	buffer[1] = addr & 0xff;
82bd985160SHans Verkuil 	buffer[2] = value;
83bd985160SHans Verkuil 	return i2c_master_send(client, buffer, 3);
84bd985160SHans Verkuil }
85bd985160SHans Verkuil 
cx25840_write4(struct i2c_client * client,u16 addr,u32 value)86bd985160SHans Verkuil int cx25840_write4(struct i2c_client *client, u16 addr, u32 value)
87bd985160SHans Verkuil {
88bd985160SHans Verkuil 	u8 buffer[6];
8910a34367SMauro Carvalho Chehab 
90bd985160SHans Verkuil 	buffer[0] = addr >> 8;
91bd985160SHans Verkuil 	buffer[1] = addr & 0xff;
924a56eb3fSHans Verkuil 	buffer[2] = value & 0xff;
934a56eb3fSHans Verkuil 	buffer[3] = (value >> 8) & 0xff;
944a56eb3fSHans Verkuil 	buffer[4] = (value >> 16) & 0xff;
954a56eb3fSHans Verkuil 	buffer[5] = value >> 24;
96bd985160SHans Verkuil 	return i2c_master_send(client, buffer, 6);
97bd985160SHans Verkuil }
98bd985160SHans Verkuil 
cx25840_read(struct i2c_client * client,u16 addr)99bd985160SHans Verkuil u8 cx25840_read(struct i2c_client *client, u16 addr)
100bd985160SHans Verkuil {
1015f272644SAndy Walls 	struct i2c_msg msgs[2];
1025f272644SAndy Walls 	u8 tx_buf[2], rx_buf[1];
103bd985160SHans Verkuil 
1045f272644SAndy Walls 	/* Write register address */
1055f272644SAndy Walls 	tx_buf[0] = addr >> 8;
1065f272644SAndy Walls 	tx_buf[1] = addr & 0xff;
1075f272644SAndy Walls 	msgs[0].addr = client->addr;
1085f272644SAndy Walls 	msgs[0].flags = 0;
1095f272644SAndy Walls 	msgs[0].len = 2;
1105f272644SAndy Walls 	msgs[0].buf = (char *)tx_buf;
1115f272644SAndy Walls 
1125f272644SAndy Walls 	/* Read data from register */
1135f272644SAndy Walls 	msgs[1].addr = client->addr;
1145f272644SAndy Walls 	msgs[1].flags = I2C_M_RD;
1155f272644SAndy Walls 	msgs[1].len = 1;
1165f272644SAndy Walls 	msgs[1].buf = (char *)rx_buf;
1175f272644SAndy Walls 
1185f272644SAndy Walls 	if (i2c_transfer(client->adapter, msgs, 2) < 2)
119bd985160SHans Verkuil 		return 0;
120bd985160SHans Verkuil 
1215f272644SAndy Walls 	return rx_buf[0];
122bd985160SHans Verkuil }
123bd985160SHans Verkuil 
cx25840_read4(struct i2c_client * client,u16 addr)124bd985160SHans Verkuil u32 cx25840_read4(struct i2c_client *client, u16 addr)
125bd985160SHans Verkuil {
1265f272644SAndy Walls 	struct i2c_msg msgs[2];
1275f272644SAndy Walls 	u8 tx_buf[2], rx_buf[4];
128bd985160SHans Verkuil 
1295f272644SAndy Walls 	/* Write register address */
1305f272644SAndy Walls 	tx_buf[0] = addr >> 8;
1315f272644SAndy Walls 	tx_buf[1] = addr & 0xff;
1325f272644SAndy Walls 	msgs[0].addr = client->addr;
1335f272644SAndy Walls 	msgs[0].flags = 0;
1345f272644SAndy Walls 	msgs[0].len = 2;
1355f272644SAndy Walls 	msgs[0].buf = (char *)tx_buf;
1365f272644SAndy Walls 
1375f272644SAndy Walls 	/* Read data from registers */
1385f272644SAndy Walls 	msgs[1].addr = client->addr;
1395f272644SAndy Walls 	msgs[1].flags = I2C_M_RD;
1405f272644SAndy Walls 	msgs[1].len = 4;
1415f272644SAndy Walls 	msgs[1].buf = (char *)rx_buf;
1425f272644SAndy Walls 
1435f272644SAndy Walls 	if (i2c_transfer(client->adapter, msgs, 2) < 2)
144bd985160SHans Verkuil 		return 0;
145bd985160SHans Verkuil 
1465f272644SAndy Walls 	return (rx_buf[3] << 24) | (rx_buf[2] << 16) | (rx_buf[1] << 8) |
1475f272644SAndy Walls 		rx_buf[0];
148bd985160SHans Verkuil }
149bd985160SHans Verkuil 
cx25840_and_or(struct i2c_client * client,u16 addr,unsigned int and_mask,u8 or_value)15010a34367SMauro Carvalho Chehab int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned int and_mask,
151bd985160SHans Verkuil 		   u8 or_value)
152bd985160SHans Verkuil {
153bd985160SHans Verkuil 	return cx25840_write(client, addr,
154bd985160SHans Verkuil 			     (cx25840_read(client, addr) & and_mask) |
155bd985160SHans Verkuil 			     or_value);
156bd985160SHans Verkuil }
157bd985160SHans Verkuil 
cx25840_and_or4(struct i2c_client * client,u16 addr,u32 and_mask,u32 or_value)15852fd3ddaSAndy Walls int cx25840_and_or4(struct i2c_client *client, u16 addr, u32 and_mask,
15952fd3ddaSAndy Walls 		    u32 or_value)
16052fd3ddaSAndy Walls {
16152fd3ddaSAndy Walls 	return cx25840_write4(client, addr,
16252fd3ddaSAndy Walls 			      (cx25840_read4(client, addr) & and_mask) |
16352fd3ddaSAndy Walls 			      or_value);
16452fd3ddaSAndy Walls }
16552fd3ddaSAndy Walls 
166bd985160SHans Verkuil /* ----------------------------------------------------------------------- */
167bd985160SHans Verkuil 
16810a34367SMauro Carvalho Chehab static int set_input(struct i2c_client *client,
16910a34367SMauro Carvalho Chehab 		     enum cx25840_video_input vid_input,
170a8bbf12aSHans Verkuil 		     enum cx25840_audio_input aud_input);
171bd985160SHans Verkuil 
172bd985160SHans Verkuil /* ----------------------------------------------------------------------- */
173bd985160SHans Verkuil 
cx23885_s_io_pin_config(struct v4l2_subdev * sd,size_t n,struct v4l2_subdev_io_pin_config * p)174d06d5777SAndy Walls static int cx23885_s_io_pin_config(struct v4l2_subdev *sd, size_t n,
175d06d5777SAndy Walls 				   struct v4l2_subdev_io_pin_config *p)
176d06d5777SAndy Walls {
177d06d5777SAndy Walls 	struct i2c_client *client = v4l2_get_subdevdata(sd);
178d06d5777SAndy Walls 	int i;
179d06d5777SAndy Walls 	u32 pin_ctrl;
180d06d5777SAndy Walls 	u8 gpio_oe, gpio_data, strength;
181d06d5777SAndy Walls 
182d06d5777SAndy Walls 	pin_ctrl = cx25840_read4(client, 0x120);
183d06d5777SAndy Walls 	gpio_oe = cx25840_read(client, 0x160);
184d06d5777SAndy Walls 	gpio_data = cx25840_read(client, 0x164);
185d06d5777SAndy Walls 
186d06d5777SAndy Walls 	for (i = 0; i < n; i++) {
187d06d5777SAndy Walls 		strength = p[i].strength;
188d06d5777SAndy Walls 		if (strength > CX25840_PIN_DRIVE_FAST)
189d06d5777SAndy Walls 			strength = CX25840_PIN_DRIVE_FAST;
190d06d5777SAndy Walls 
191d06d5777SAndy Walls 		switch (p[i].pin) {
192d06d5777SAndy Walls 		case CX23885_PIN_IRQ_N_GPIO16:
193d06d5777SAndy Walls 			if (p[i].function != CX23885_PAD_IRQ_N) {
194d06d5777SAndy Walls 				/* GPIO16 */
195d06d5777SAndy Walls 				pin_ctrl &= ~(0x1 << 25);
196d06d5777SAndy Walls 			} else {
197d06d5777SAndy Walls 				/* IRQ_N */
198d06d5777SAndy Walls 				if (p[i].flags &
1994eb2f557SMauro Carvalho Chehab 					(BIT(V4L2_SUBDEV_IO_PIN_DISABLE) |
2004eb2f557SMauro Carvalho Chehab 					 BIT(V4L2_SUBDEV_IO_PIN_INPUT))) {
201d06d5777SAndy Walls 					pin_ctrl &= ~(0x1 << 25);
202d06d5777SAndy Walls 				} else {
203d06d5777SAndy Walls 					pin_ctrl |= (0x1 << 25);
204d06d5777SAndy Walls 				}
205d06d5777SAndy Walls 				if (p[i].flags &
2064eb2f557SMauro Carvalho Chehab 					BIT(V4L2_SUBDEV_IO_PIN_ACTIVE_LOW)) {
207d06d5777SAndy Walls 					pin_ctrl &= ~(0x1 << 24);
208d06d5777SAndy Walls 				} else {
209d06d5777SAndy Walls 					pin_ctrl |= (0x1 << 24);
210d06d5777SAndy Walls 				}
211d06d5777SAndy Walls 			}
212d06d5777SAndy Walls 			break;
213d06d5777SAndy Walls 		case CX23885_PIN_IR_RX_GPIO19:
214d06d5777SAndy Walls 			if (p[i].function != CX23885_PAD_GPIO19) {
215d06d5777SAndy Walls 				/* IR_RX */
216d06d5777SAndy Walls 				gpio_oe |= (0x1 << 0);
217d06d5777SAndy Walls 				pin_ctrl &= ~(0x3 << 18);
218d06d5777SAndy Walls 				pin_ctrl |= (strength << 18);
219d06d5777SAndy Walls 			} else {
220d06d5777SAndy Walls 				/* GPIO19 */
221d06d5777SAndy Walls 				gpio_oe &= ~(0x1 << 0);
2224eb2f557SMauro Carvalho Chehab 				if (p[i].flags & BIT(V4L2_SUBDEV_IO_PIN_SET_VALUE)) {
223d06d5777SAndy Walls 					gpio_data &= ~(0x1 << 0);
224d06d5777SAndy Walls 					gpio_data |= ((p[i].value & 0x1) << 0);
225d06d5777SAndy Walls 				}
226d06d5777SAndy Walls 				pin_ctrl &= ~(0x3 << 12);
227d06d5777SAndy Walls 				pin_ctrl |= (strength << 12);
228d06d5777SAndy Walls 			}
229d06d5777SAndy Walls 			break;
230d06d5777SAndy Walls 		case CX23885_PIN_IR_TX_GPIO20:
231d06d5777SAndy Walls 			if (p[i].function != CX23885_PAD_GPIO20) {
232d06d5777SAndy Walls 				/* IR_TX */
233d06d5777SAndy Walls 				gpio_oe |= (0x1 << 1);
2344eb2f557SMauro Carvalho Chehab 				if (p[i].flags & BIT(V4L2_SUBDEV_IO_PIN_DISABLE))
235d06d5777SAndy Walls 					pin_ctrl &= ~(0x1 << 10);
236d06d5777SAndy Walls 				else
237d06d5777SAndy Walls 					pin_ctrl |= (0x1 << 10);
238d06d5777SAndy Walls 				pin_ctrl &= ~(0x3 << 18);
239d06d5777SAndy Walls 				pin_ctrl |= (strength << 18);
240d06d5777SAndy Walls 			} else {
241d06d5777SAndy Walls 				/* GPIO20 */
242d06d5777SAndy Walls 				gpio_oe &= ~(0x1 << 1);
2434eb2f557SMauro Carvalho Chehab 				if (p[i].flags & BIT(V4L2_SUBDEV_IO_PIN_SET_VALUE)) {
244d06d5777SAndy Walls 					gpio_data &= ~(0x1 << 1);
245d06d5777SAndy Walls 					gpio_data |= ((p[i].value & 0x1) << 1);
246d06d5777SAndy Walls 				}
247d06d5777SAndy Walls 				pin_ctrl &= ~(0x3 << 12);
248d06d5777SAndy Walls 				pin_ctrl |= (strength << 12);
249d06d5777SAndy Walls 			}
250d06d5777SAndy Walls 			break;
251d06d5777SAndy Walls 		case CX23885_PIN_I2S_SDAT_GPIO21:
252d06d5777SAndy Walls 			if (p[i].function != CX23885_PAD_GPIO21) {
253d06d5777SAndy Walls 				/* I2S_SDAT */
254d06d5777SAndy Walls 				/* TODO: Input or Output config */
255d06d5777SAndy Walls 				gpio_oe |= (0x1 << 2);
256d06d5777SAndy Walls 				pin_ctrl &= ~(0x3 << 22);
257d06d5777SAndy Walls 				pin_ctrl |= (strength << 22);
258d06d5777SAndy Walls 			} else {
259d06d5777SAndy Walls 				/* GPIO21 */
260d06d5777SAndy Walls 				gpio_oe &= ~(0x1 << 2);
2614eb2f557SMauro Carvalho Chehab 				if (p[i].flags & BIT(V4L2_SUBDEV_IO_PIN_SET_VALUE)) {
262d06d5777SAndy Walls 					gpio_data &= ~(0x1 << 2);
263d06d5777SAndy Walls 					gpio_data |= ((p[i].value & 0x1) << 2);
264d06d5777SAndy Walls 				}
265d06d5777SAndy Walls 				pin_ctrl &= ~(0x3 << 12);
266d06d5777SAndy Walls 				pin_ctrl |= (strength << 12);
267d06d5777SAndy Walls 			}
268d06d5777SAndy Walls 			break;
269d06d5777SAndy Walls 		case CX23885_PIN_I2S_WCLK_GPIO22:
270d06d5777SAndy Walls 			if (p[i].function != CX23885_PAD_GPIO22) {
271d06d5777SAndy Walls 				/* I2S_WCLK */
272d06d5777SAndy Walls 				/* TODO: Input or Output config */
273d06d5777SAndy Walls 				gpio_oe |= (0x1 << 3);
274d06d5777SAndy Walls 				pin_ctrl &= ~(0x3 << 22);
275d06d5777SAndy Walls 				pin_ctrl |= (strength << 22);
276d06d5777SAndy Walls 			} else {
277d06d5777SAndy Walls 				/* GPIO22 */
278d06d5777SAndy Walls 				gpio_oe &= ~(0x1 << 3);
2794eb2f557SMauro Carvalho Chehab 				if (p[i].flags & BIT(V4L2_SUBDEV_IO_PIN_SET_VALUE)) {
280d06d5777SAndy Walls 					gpio_data &= ~(0x1 << 3);
281d06d5777SAndy Walls 					gpio_data |= ((p[i].value & 0x1) << 3);
282d06d5777SAndy Walls 				}
283d06d5777SAndy Walls 				pin_ctrl &= ~(0x3 << 12);
284d06d5777SAndy Walls 				pin_ctrl |= (strength << 12);
285d06d5777SAndy Walls 			}
286d06d5777SAndy Walls 			break;
287d06d5777SAndy Walls 		case CX23885_PIN_I2S_BCLK_GPIO23:
288d06d5777SAndy Walls 			if (p[i].function != CX23885_PAD_GPIO23) {
289d06d5777SAndy Walls 				/* I2S_BCLK */
290d06d5777SAndy Walls 				/* TODO: Input or Output config */
291d06d5777SAndy Walls 				gpio_oe |= (0x1 << 4);
292d06d5777SAndy Walls 				pin_ctrl &= ~(0x3 << 22);
293d06d5777SAndy Walls 				pin_ctrl |= (strength << 22);
294d06d5777SAndy Walls 			} else {
295d06d5777SAndy Walls 				/* GPIO23 */
296d06d5777SAndy Walls 				gpio_oe &= ~(0x1 << 4);
2974eb2f557SMauro Carvalho Chehab 				if (p[i].flags & BIT(V4L2_SUBDEV_IO_PIN_SET_VALUE)) {
298d06d5777SAndy Walls 					gpio_data &= ~(0x1 << 4);
299d06d5777SAndy Walls 					gpio_data |= ((p[i].value & 0x1) << 4);
300d06d5777SAndy Walls 				}
301d06d5777SAndy Walls 				pin_ctrl &= ~(0x3 << 12);
302d06d5777SAndy Walls 				pin_ctrl |= (strength << 12);
303d06d5777SAndy Walls 			}
304d06d5777SAndy Walls 			break;
305d06d5777SAndy Walls 		}
306d06d5777SAndy Walls 	}
307d06d5777SAndy Walls 
308d06d5777SAndy Walls 	cx25840_write(client, 0x164, gpio_data);
309d06d5777SAndy Walls 	cx25840_write(client, 0x160, gpio_oe);
310d06d5777SAndy Walls 	cx25840_write4(client, 0x120, pin_ctrl);
311d06d5777SAndy Walls 	return 0;
312d06d5777SAndy Walls }
313d06d5777SAndy Walls 
cx25840_function_to_pad(struct i2c_client * client,u8 function)314e81a9076SMaciej S. Szmigiero static u8 cx25840_function_to_pad(struct i2c_client *client, u8 function)
315e81a9076SMaciej S. Szmigiero {
316e81a9076SMaciej S. Szmigiero 	if (function > CX25840_PAD_VRESET) {
317e81a9076SMaciej S. Szmigiero 		v4l_err(client, "invalid function %u, assuming default\n",
318e81a9076SMaciej S. Szmigiero 			(unsigned int)function);
319e81a9076SMaciej S. Szmigiero 		return 0;
320e81a9076SMaciej S. Szmigiero 	}
321e81a9076SMaciej S. Szmigiero 
322e81a9076SMaciej S. Szmigiero 	return function;
323e81a9076SMaciej S. Szmigiero }
324e81a9076SMaciej S. Szmigiero 
cx25840_set_invert(u8 * pinctrl3,u8 * voutctrl4,u8 function,u8 pin,bool invert)325e81a9076SMaciej S. Szmigiero static void cx25840_set_invert(u8 *pinctrl3, u8 *voutctrl4, u8 function,
326e81a9076SMaciej S. Szmigiero 			       u8 pin, bool invert)
327e81a9076SMaciej S. Szmigiero {
328e81a9076SMaciej S. Szmigiero 	switch (function) {
329e81a9076SMaciej S. Szmigiero 	case CX25840_PAD_IRQ_N:
330e81a9076SMaciej S. Szmigiero 		if (invert)
331e81a9076SMaciej S. Szmigiero 			*pinctrl3 &= ~2;
332e81a9076SMaciej S. Szmigiero 		else
333e81a9076SMaciej S. Szmigiero 			*pinctrl3 |= 2;
334e81a9076SMaciej S. Szmigiero 		break;
335e81a9076SMaciej S. Szmigiero 
336e81a9076SMaciej S. Szmigiero 	case CX25840_PAD_ACTIVE:
337e81a9076SMaciej S. Szmigiero 		if (invert)
338e81a9076SMaciej S. Szmigiero 			*voutctrl4 |= BIT(2);
339e81a9076SMaciej S. Szmigiero 		else
340e81a9076SMaciej S. Szmigiero 			*voutctrl4 &= ~BIT(2);
341e81a9076SMaciej S. Szmigiero 		break;
342e81a9076SMaciej S. Szmigiero 
343e81a9076SMaciej S. Szmigiero 	case CX25840_PAD_VACTIVE:
344e81a9076SMaciej S. Szmigiero 		if (invert)
345e81a9076SMaciej S. Szmigiero 			*voutctrl4 |= BIT(5);
346e81a9076SMaciej S. Szmigiero 		else
347e81a9076SMaciej S. Szmigiero 			*voutctrl4 &= ~BIT(5);
348e81a9076SMaciej S. Szmigiero 		break;
349e81a9076SMaciej S. Szmigiero 
350e81a9076SMaciej S. Szmigiero 	case CX25840_PAD_CBFLAG:
351e81a9076SMaciej S. Szmigiero 		if (invert)
352e81a9076SMaciej S. Szmigiero 			*voutctrl4 |= BIT(4);
353e81a9076SMaciej S. Szmigiero 		else
354e81a9076SMaciej S. Szmigiero 			*voutctrl4 &= ~BIT(4);
355e81a9076SMaciej S. Szmigiero 		break;
356e81a9076SMaciej S. Szmigiero 
357e81a9076SMaciej S. Szmigiero 	case CX25840_PAD_VRESET:
358e81a9076SMaciej S. Szmigiero 		if (invert)
359e81a9076SMaciej S. Szmigiero 			*voutctrl4 |= BIT(0);
360e81a9076SMaciej S. Szmigiero 		else
361e81a9076SMaciej S. Szmigiero 			*voutctrl4 &= ~BIT(0);
362e81a9076SMaciej S. Szmigiero 		break;
363e81a9076SMaciej S. Szmigiero 	}
364e81a9076SMaciej S. Szmigiero 
365e81a9076SMaciej S. Szmigiero 	if (function != CX25840_PAD_DEFAULT)
366e81a9076SMaciej S. Szmigiero 		return;
367e81a9076SMaciej S. Szmigiero 
368e81a9076SMaciej S. Szmigiero 	switch (pin) {
369e81a9076SMaciej S. Szmigiero 	case CX25840_PIN_DVALID_PRGM0:
370e81a9076SMaciej S. Szmigiero 		if (invert)
371e81a9076SMaciej S. Szmigiero 			*voutctrl4 |= BIT(6);
372e81a9076SMaciej S. Szmigiero 		else
373e81a9076SMaciej S. Szmigiero 			*voutctrl4 &= ~BIT(6);
374e81a9076SMaciej S. Szmigiero 		break;
375e81a9076SMaciej S. Szmigiero 
376e81a9076SMaciej S. Szmigiero 	case CX25840_PIN_HRESET_PRGM2:
377e81a9076SMaciej S. Szmigiero 		if (invert)
378e81a9076SMaciej S. Szmigiero 			*voutctrl4 |= BIT(1);
379e81a9076SMaciej S. Szmigiero 		else
380e81a9076SMaciej S. Szmigiero 			*voutctrl4 &= ~BIT(1);
381e81a9076SMaciej S. Szmigiero 		break;
382e81a9076SMaciej S. Szmigiero 	}
383e81a9076SMaciej S. Szmigiero }
384e81a9076SMaciej S. Szmigiero 
cx25840_s_io_pin_config(struct v4l2_subdev * sd,size_t n,struct v4l2_subdev_io_pin_config * p)385e81a9076SMaciej S. Szmigiero static int cx25840_s_io_pin_config(struct v4l2_subdev *sd, size_t n,
386e81a9076SMaciej S. Szmigiero 				   struct v4l2_subdev_io_pin_config *p)
387e81a9076SMaciej S. Szmigiero {
388e81a9076SMaciej S. Szmigiero 	struct i2c_client *client = v4l2_get_subdevdata(sd);
389e81a9076SMaciej S. Szmigiero 	unsigned int i;
390e81a9076SMaciej S. Szmigiero 	u8 pinctrl[6], pinconf[10], voutctrl4;
391e81a9076SMaciej S. Szmigiero 
392e81a9076SMaciej S. Szmigiero 	for (i = 0; i < 6; i++)
393e81a9076SMaciej S. Szmigiero 		pinctrl[i] = cx25840_read(client, 0x114 + i);
394e81a9076SMaciej S. Szmigiero 
395e81a9076SMaciej S. Szmigiero 	for (i = 0; i < 10; i++)
396e81a9076SMaciej S. Szmigiero 		pinconf[i] = cx25840_read(client, 0x11c + i);
397e81a9076SMaciej S. Szmigiero 
398e81a9076SMaciej S. Szmigiero 	voutctrl4 = cx25840_read(client, 0x407);
399e81a9076SMaciej S. Szmigiero 
400e81a9076SMaciej S. Szmigiero 	for (i = 0; i < n; i++) {
401e81a9076SMaciej S. Szmigiero 		u8 strength = p[i].strength;
402e81a9076SMaciej S. Szmigiero 
403e81a9076SMaciej S. Szmigiero 		if (strength != CX25840_PIN_DRIVE_SLOW &&
404e81a9076SMaciej S. Szmigiero 		    strength != CX25840_PIN_DRIVE_MEDIUM &&
405e81a9076SMaciej S. Szmigiero 		    strength != CX25840_PIN_DRIVE_FAST) {
406e81a9076SMaciej S. Szmigiero 			v4l_err(client,
407e81a9076SMaciej S. Szmigiero 				"invalid drive speed for pin %u (%u), assuming fast\n",
408e81a9076SMaciej S. Szmigiero 				(unsigned int)p[i].pin,
409e81a9076SMaciej S. Szmigiero 				(unsigned int)strength);
410e81a9076SMaciej S. Szmigiero 
411e81a9076SMaciej S. Szmigiero 			strength = CX25840_PIN_DRIVE_FAST;
412e81a9076SMaciej S. Szmigiero 		}
413e81a9076SMaciej S. Szmigiero 
414e81a9076SMaciej S. Szmigiero 		switch (p[i].pin) {
415e81a9076SMaciej S. Szmigiero 		case CX25840_PIN_DVALID_PRGM0:
416e81a9076SMaciej S. Szmigiero 			if (p[i].flags & BIT(V4L2_SUBDEV_IO_PIN_DISABLE))
417e81a9076SMaciej S. Szmigiero 				pinctrl[0] &= ~BIT(6);
418e81a9076SMaciej S. Szmigiero 			else
419e81a9076SMaciej S. Szmigiero 				pinctrl[0] |= BIT(6);
420e81a9076SMaciej S. Szmigiero 
421e81a9076SMaciej S. Szmigiero 			pinconf[3] &= 0xf0;
422e81a9076SMaciej S. Szmigiero 			pinconf[3] |= cx25840_function_to_pad(client,
423e81a9076SMaciej S. Szmigiero 							      p[i].function);
424e81a9076SMaciej S. Szmigiero 
425e81a9076SMaciej S. Szmigiero 			cx25840_set_invert(&pinctrl[3], &voutctrl4,
426e81a9076SMaciej S. Szmigiero 					   p[i].function,
427e81a9076SMaciej S. Szmigiero 					   CX25840_PIN_DVALID_PRGM0,
428e81a9076SMaciej S. Szmigiero 					   p[i].flags &
429e81a9076SMaciej S. Szmigiero 					   BIT(V4L2_SUBDEV_IO_PIN_ACTIVE_LOW));
430e81a9076SMaciej S. Szmigiero 
431e81a9076SMaciej S. Szmigiero 			pinctrl[4] &= ~(3 << 2); /* CX25840_PIN_DRIVE_MEDIUM */
432e81a9076SMaciej S. Szmigiero 			switch (strength) {
433e81a9076SMaciej S. Szmigiero 			case CX25840_PIN_DRIVE_SLOW:
434e81a9076SMaciej S. Szmigiero 				pinctrl[4] |= 1 << 2;
435e81a9076SMaciej S. Szmigiero 				break;
436e81a9076SMaciej S. Szmigiero 
437e81a9076SMaciej S. Szmigiero 			case CX25840_PIN_DRIVE_FAST:
438e81a9076SMaciej S. Szmigiero 				pinctrl[4] |= 2 << 2;
439e81a9076SMaciej S. Szmigiero 				break;
440e81a9076SMaciej S. Szmigiero 			}
441e81a9076SMaciej S. Szmigiero 
442e81a9076SMaciej S. Szmigiero 			break;
443e81a9076SMaciej S. Szmigiero 
444e81a9076SMaciej S. Szmigiero 		case CX25840_PIN_HRESET_PRGM2:
445e81a9076SMaciej S. Szmigiero 			if (p[i].flags & BIT(V4L2_SUBDEV_IO_PIN_DISABLE))
446e81a9076SMaciej S. Szmigiero 				pinctrl[1] &= ~BIT(0);
447e81a9076SMaciej S. Szmigiero 			else
448e81a9076SMaciej S. Szmigiero 				pinctrl[1] |= BIT(0);
449e81a9076SMaciej S. Szmigiero 
450e81a9076SMaciej S. Szmigiero 			pinconf[4] &= 0xf0;
451e81a9076SMaciej S. Szmigiero 			pinconf[4] |= cx25840_function_to_pad(client,
452e81a9076SMaciej S. Szmigiero 							      p[i].function);
453e81a9076SMaciej S. Szmigiero 
454e81a9076SMaciej S. Szmigiero 			cx25840_set_invert(&pinctrl[3], &voutctrl4,
455e81a9076SMaciej S. Szmigiero 					   p[i].function,
456e81a9076SMaciej S. Szmigiero 					   CX25840_PIN_HRESET_PRGM2,
457e81a9076SMaciej S. Szmigiero 					   p[i].flags &
458e81a9076SMaciej S. Szmigiero 					   BIT(V4L2_SUBDEV_IO_PIN_ACTIVE_LOW));
459e81a9076SMaciej S. Szmigiero 
460e81a9076SMaciej S. Szmigiero 			pinctrl[4] &= ~(3 << 2); /* CX25840_PIN_DRIVE_MEDIUM */
461e81a9076SMaciej S. Szmigiero 			switch (strength) {
462e81a9076SMaciej S. Szmigiero 			case CX25840_PIN_DRIVE_SLOW:
463e81a9076SMaciej S. Szmigiero 				pinctrl[4] |= 1 << 2;
464e81a9076SMaciej S. Szmigiero 				break;
465e81a9076SMaciej S. Szmigiero 
466e81a9076SMaciej S. Szmigiero 			case CX25840_PIN_DRIVE_FAST:
467e81a9076SMaciej S. Szmigiero 				pinctrl[4] |= 2 << 2;
468e81a9076SMaciej S. Szmigiero 				break;
469e81a9076SMaciej S. Szmigiero 			}
470e81a9076SMaciej S. Szmigiero 
471e81a9076SMaciej S. Szmigiero 			break;
472e81a9076SMaciej S. Szmigiero 
473e81a9076SMaciej S. Szmigiero 		case CX25840_PIN_PLL_CLK_PRGM7:
474e81a9076SMaciej S. Szmigiero 			if (p[i].flags & BIT(V4L2_SUBDEV_IO_PIN_DISABLE))
475e81a9076SMaciej S. Szmigiero 				pinctrl[2] &= ~BIT(2);
476e81a9076SMaciej S. Szmigiero 			else
477e81a9076SMaciej S. Szmigiero 				pinctrl[2] |= BIT(2);
478e81a9076SMaciej S. Szmigiero 
479e81a9076SMaciej S. Szmigiero 			switch (p[i].function) {
480e81a9076SMaciej S. Szmigiero 			case CX25840_PAD_XTI_X5_DLL:
481e81a9076SMaciej S. Szmigiero 				pinconf[6] = 0;
482e81a9076SMaciej S. Szmigiero 				break;
483e81a9076SMaciej S. Szmigiero 
484e81a9076SMaciej S. Szmigiero 			case CX25840_PAD_AUX_PLL:
485e81a9076SMaciej S. Szmigiero 				pinconf[6] = 1;
486e81a9076SMaciej S. Szmigiero 				break;
487e81a9076SMaciej S. Szmigiero 
488e81a9076SMaciej S. Szmigiero 			case CX25840_PAD_VID_PLL:
489e81a9076SMaciej S. Szmigiero 				pinconf[6] = 5;
490e81a9076SMaciej S. Szmigiero 				break;
491e81a9076SMaciej S. Szmigiero 
492e81a9076SMaciej S. Szmigiero 			case CX25840_PAD_XTI:
493e81a9076SMaciej S. Szmigiero 				pinconf[6] = 2;
494e81a9076SMaciej S. Szmigiero 				break;
495e81a9076SMaciej S. Szmigiero 
496e81a9076SMaciej S. Szmigiero 			default:
497e81a9076SMaciej S. Szmigiero 				pinconf[6] = 3;
498e81a9076SMaciej S. Szmigiero 				pinconf[6] |=
499e81a9076SMaciej S. Szmigiero 					cx25840_function_to_pad(client,
500e81a9076SMaciej S. Szmigiero 								p[i].function)
501e81a9076SMaciej S. Szmigiero 					<< 4;
502e81a9076SMaciej S. Szmigiero 			}
503e81a9076SMaciej S. Szmigiero 
504e81a9076SMaciej S. Szmigiero 			break;
505e81a9076SMaciej S. Szmigiero 
506e81a9076SMaciej S. Szmigiero 		default:
507e81a9076SMaciej S. Szmigiero 			v4l_err(client, "invalid or unsupported pin %u\n",
508e81a9076SMaciej S. Szmigiero 				(unsigned int)p[i].pin);
509e81a9076SMaciej S. Szmigiero 			break;
510e81a9076SMaciej S. Szmigiero 		}
511e81a9076SMaciej S. Szmigiero 	}
512e81a9076SMaciej S. Szmigiero 
513e81a9076SMaciej S. Szmigiero 	cx25840_write(client, 0x407, voutctrl4);
514e81a9076SMaciej S. Szmigiero 
515e81a9076SMaciej S. Szmigiero 	for (i = 0; i < 6; i++)
516e81a9076SMaciej S. Szmigiero 		cx25840_write(client, 0x114 + i, pinctrl[i]);
517e81a9076SMaciej S. Szmigiero 
518e81a9076SMaciej S. Szmigiero 	for (i = 0; i < 10; i++)
519e81a9076SMaciej S. Szmigiero 		cx25840_write(client, 0x11c + i, pinconf[i]);
520e81a9076SMaciej S. Szmigiero 
521e81a9076SMaciej S. Szmigiero 	return 0;
522e81a9076SMaciej S. Szmigiero }
523e81a9076SMaciej S. Szmigiero 
common_s_io_pin_config(struct v4l2_subdev * sd,size_t n,struct v4l2_subdev_io_pin_config * pincfg)524d06d5777SAndy Walls static int common_s_io_pin_config(struct v4l2_subdev *sd, size_t n,
525d06d5777SAndy Walls 				  struct v4l2_subdev_io_pin_config *pincfg)
526d06d5777SAndy Walls {
527d06d5777SAndy Walls 	struct cx25840_state *state = to_state(sd);
528d06d5777SAndy Walls 
529d06d5777SAndy Walls 	if (is_cx2388x(state))
530d06d5777SAndy Walls 		return cx23885_s_io_pin_config(sd, n, pincfg);
531e81a9076SMaciej S. Szmigiero 	else if (is_cx2584x(state))
532e81a9076SMaciej S. Szmigiero 		return cx25840_s_io_pin_config(sd, n, pincfg);
533d06d5777SAndy Walls 	return 0;
534d06d5777SAndy Walls }
535d06d5777SAndy Walls 
536d06d5777SAndy Walls /* ----------------------------------------------------------------------- */
537d06d5777SAndy Walls 
init_dll1(struct i2c_client * client)538d92c20e0SHans Verkuil static void init_dll1(struct i2c_client *client)
539bd985160SHans Verkuil {
54010a34367SMauro Carvalho Chehab 	/*
54110a34367SMauro Carvalho Chehab 	 * This is the Hauppauge sequence used to
54210a34367SMauro Carvalho Chehab 	 * initialize the Delay Lock Loop 1 (ADC DLL).
54310a34367SMauro Carvalho Chehab 	 */
544bd985160SHans Verkuil 	cx25840_write(client, 0x159, 0x23);
545bd985160SHans Verkuil 	cx25840_write(client, 0x15a, 0x87);
546bd985160SHans Verkuil 	cx25840_write(client, 0x15b, 0x06);
54738051450STyler Trafford 	udelay(10);
548bd985160SHans Verkuil 	cx25840_write(client, 0x159, 0xe1);
54938051450STyler Trafford 	udelay(10);
550bd985160SHans Verkuil 	cx25840_write(client, 0x15a, 0x86);
551bd985160SHans Verkuil 	cx25840_write(client, 0x159, 0xe0);
552bd985160SHans Verkuil 	cx25840_write(client, 0x159, 0xe1);
553bd985160SHans Verkuil 	cx25840_write(client, 0x15b, 0x10);
554bd985160SHans Verkuil }
555bd985160SHans Verkuil 
init_dll2(struct i2c_client * client)556d92c20e0SHans Verkuil static void init_dll2(struct i2c_client *client)
557bd985160SHans Verkuil {
55810a34367SMauro Carvalho Chehab 	/*
55910a34367SMauro Carvalho Chehab 	 * This is the Hauppauge sequence used to
56010a34367SMauro Carvalho Chehab 	 * initialize the Delay Lock Loop 2 (ADC DLL).
56110a34367SMauro Carvalho Chehab 	 */
562bd985160SHans Verkuil 	cx25840_write(client, 0x15d, 0xe3);
563bd985160SHans Verkuil 	cx25840_write(client, 0x15e, 0x86);
564bd985160SHans Verkuil 	cx25840_write(client, 0x15f, 0x06);
56538051450STyler Trafford 	udelay(10);
566bd985160SHans Verkuil 	cx25840_write(client, 0x15d, 0xe1);
567bd985160SHans Verkuil 	cx25840_write(client, 0x15d, 0xe0);
568bd985160SHans Verkuil 	cx25840_write(client, 0x15d, 0xe1);
569bd985160SHans Verkuil }
570bd985160SHans Verkuil 
cx25836_initialize(struct i2c_client * client)571e2b8cf4cSHans Verkuil static void cx25836_initialize(struct i2c_client *client)
572e2b8cf4cSHans Verkuil {
57310a34367SMauro Carvalho Chehab 	/*
57410a34367SMauro Carvalho Chehab 	 *reset configuration is described on page 3-77
57510a34367SMauro Carvalho Chehab 	 * of the CX25836 datasheet
57610a34367SMauro Carvalho Chehab 	 */
57710a34367SMauro Carvalho Chehab 
578e2b8cf4cSHans Verkuil 	/* 2. */
579e2b8cf4cSHans Verkuil 	cx25840_and_or(client, 0x000, ~0x01, 0x01);
580e2b8cf4cSHans Verkuil 	cx25840_and_or(client, 0x000, ~0x01, 0x00);
581e2b8cf4cSHans Verkuil 	/* 3a. */
582e2b8cf4cSHans Verkuil 	cx25840_and_or(client, 0x15a, ~0x70, 0x00);
583e2b8cf4cSHans Verkuil 	/* 3b. */
584e2b8cf4cSHans Verkuil 	cx25840_and_or(client, 0x15b, ~0x1e, 0x06);
585e2b8cf4cSHans Verkuil 	/* 3c. */
586e2b8cf4cSHans Verkuil 	cx25840_and_or(client, 0x159, ~0x02, 0x02);
587e2b8cf4cSHans Verkuil 	/* 3d. */
58838051450STyler Trafford 	udelay(10);
589e2b8cf4cSHans Verkuil 	/* 3e. */
590e2b8cf4cSHans Verkuil 	cx25840_and_or(client, 0x159, ~0x02, 0x00);
591e2b8cf4cSHans Verkuil 	/* 3f. */
592e2b8cf4cSHans Verkuil 	cx25840_and_or(client, 0x159, ~0xc0, 0xc0);
593e2b8cf4cSHans Verkuil 	/* 3g. */
594e2b8cf4cSHans Verkuil 	cx25840_and_or(client, 0x159, ~0x01, 0x00);
595e2b8cf4cSHans Verkuil 	cx25840_and_or(client, 0x159, ~0x01, 0x01);
596e2b8cf4cSHans Verkuil 	/* 3h. */
597e2b8cf4cSHans Verkuil 	cx25840_and_or(client, 0x15b, ~0x1e, 0x10);
598e2b8cf4cSHans Verkuil }
599e2b8cf4cSHans Verkuil 
cx25840_work_handler(struct work_struct * work)60021340ae0SHans Verkuil static void cx25840_work_handler(struct work_struct *work)
60121340ae0SHans Verkuil {
60221340ae0SHans Verkuil 	struct cx25840_state *state = container_of(work, struct cx25840_state, fw_work);
60310a34367SMauro Carvalho Chehab 
60421340ae0SHans Verkuil 	cx25840_loadfw(state->c);
60521340ae0SHans Verkuil 	wake_up(&state->fw_wait);
60621340ae0SHans Verkuil }
60721340ae0SHans Verkuil 
608e81a9076SMaciej S. Szmigiero #define CX25840_VCONFIG_SET_BIT(state, opt_msk, voc, idx, bit, oneval)	\
609e81a9076SMaciej S. Szmigiero 	do {								\
610e81a9076SMaciej S. Szmigiero 		if ((state)->vid_config & (opt_msk)) {			\
611e81a9076SMaciej S. Szmigiero 			if (((state)->vid_config & (opt_msk)) ==	\
612e81a9076SMaciej S. Szmigiero 			    (oneval))					\
613e81a9076SMaciej S. Szmigiero 				(voc)[idx] |= BIT(bit);		\
614e81a9076SMaciej S. Szmigiero 			else						\
615e81a9076SMaciej S. Szmigiero 				(voc)[idx] &= ~BIT(bit);		\
616e81a9076SMaciej S. Szmigiero 		}							\
617e81a9076SMaciej S. Szmigiero 	} while (0)
618e81a9076SMaciej S. Szmigiero 
619e81a9076SMaciej S. Szmigiero /* apply current vconfig to hardware regs */
cx25840_vconfig_apply(struct i2c_client * client)620e81a9076SMaciej S. Szmigiero static void cx25840_vconfig_apply(struct i2c_client *client)
621e81a9076SMaciej S. Szmigiero {
622e81a9076SMaciej S. Szmigiero 	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
623e81a9076SMaciej S. Szmigiero 	u8 voutctrl[3];
624e81a9076SMaciej S. Szmigiero 	unsigned int i;
625e81a9076SMaciej S. Szmigiero 
626e81a9076SMaciej S. Szmigiero 	for (i = 0; i < 3; i++)
627e81a9076SMaciej S. Szmigiero 		voutctrl[i] = cx25840_read(client, 0x404 + i);
628e81a9076SMaciej S. Szmigiero 
629e81a9076SMaciej S. Szmigiero 	if (state->vid_config & CX25840_VCONFIG_FMT_MASK)
630e81a9076SMaciej S. Szmigiero 		voutctrl[0] &= ~3;
631e81a9076SMaciej S. Szmigiero 	switch (state->vid_config & CX25840_VCONFIG_FMT_MASK) {
632e81a9076SMaciej S. Szmigiero 	case CX25840_VCONFIG_FMT_BT656:
633e81a9076SMaciej S. Szmigiero 		voutctrl[0] |= 1;
634e81a9076SMaciej S. Szmigiero 		break;
635e81a9076SMaciej S. Szmigiero 
636e81a9076SMaciej S. Szmigiero 	case CX25840_VCONFIG_FMT_VIP11:
637e81a9076SMaciej S. Szmigiero 		voutctrl[0] |= 2;
638e81a9076SMaciej S. Szmigiero 		break;
639e81a9076SMaciej S. Szmigiero 
640e81a9076SMaciej S. Szmigiero 	case CX25840_VCONFIG_FMT_VIP2:
641e81a9076SMaciej S. Szmigiero 		voutctrl[0] |= 3;
642e81a9076SMaciej S. Szmigiero 		break;
643e81a9076SMaciej S. Szmigiero 
644e81a9076SMaciej S. Szmigiero 	case CX25840_VCONFIG_FMT_BT601:
645e81a9076SMaciej S. Szmigiero 		/* zero */
646e81a9076SMaciej S. Szmigiero 	default:
647e81a9076SMaciej S. Szmigiero 		break;
648e81a9076SMaciej S. Szmigiero 	}
649e81a9076SMaciej S. Szmigiero 
650e81a9076SMaciej S. Szmigiero 	CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_RES_MASK, voutctrl,
651e81a9076SMaciej S. Szmigiero 				0, 2, CX25840_VCONFIG_RES_10BIT);
652e81a9076SMaciej S. Szmigiero 	CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_VBIRAW_MASK, voutctrl,
653e81a9076SMaciej S. Szmigiero 				0, 3, CX25840_VCONFIG_VBIRAW_ENABLED);
654e81a9076SMaciej S. Szmigiero 	CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_ANCDATA_MASK, voutctrl,
655e81a9076SMaciej S. Szmigiero 				0, 4, CX25840_VCONFIG_ANCDATA_ENABLED);
656e81a9076SMaciej S. Szmigiero 	CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_TASKBIT_MASK, voutctrl,
657e81a9076SMaciej S. Szmigiero 				0, 5, CX25840_VCONFIG_TASKBIT_ONE);
658e81a9076SMaciej S. Szmigiero 	CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_ACTIVE_MASK, voutctrl,
659e81a9076SMaciej S. Szmigiero 				1, 2, CX25840_VCONFIG_ACTIVE_HORIZONTAL);
660e81a9076SMaciej S. Szmigiero 	CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_VALID_MASK, voutctrl,
661e81a9076SMaciej S. Szmigiero 				1, 3, CX25840_VCONFIG_VALID_ANDACTIVE);
662e81a9076SMaciej S. Szmigiero 	CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_HRESETW_MASK, voutctrl,
663e81a9076SMaciej S. Szmigiero 				1, 4, CX25840_VCONFIG_HRESETW_PIXCLK);
664e81a9076SMaciej S. Szmigiero 
665e81a9076SMaciej S. Szmigiero 	if (state->vid_config & CX25840_VCONFIG_CLKGATE_MASK)
666e81a9076SMaciej S. Szmigiero 		voutctrl[1] &= ~(3 << 6);
667e81a9076SMaciej S. Szmigiero 	switch (state->vid_config & CX25840_VCONFIG_CLKGATE_MASK) {
668e81a9076SMaciej S. Szmigiero 	case CX25840_VCONFIG_CLKGATE_VALID:
669e81a9076SMaciej S. Szmigiero 		voutctrl[1] |= 2;
670e81a9076SMaciej S. Szmigiero 		break;
671e81a9076SMaciej S. Szmigiero 
672e81a9076SMaciej S. Szmigiero 	case CX25840_VCONFIG_CLKGATE_VALIDACTIVE:
673e81a9076SMaciej S. Szmigiero 		voutctrl[1] |= 3;
674e81a9076SMaciej S. Szmigiero 		break;
675e81a9076SMaciej S. Szmigiero 
676e81a9076SMaciej S. Szmigiero 	case CX25840_VCONFIG_CLKGATE_NONE:
677e81a9076SMaciej S. Szmigiero 		/* zero */
678e81a9076SMaciej S. Szmigiero 	default:
679e81a9076SMaciej S. Szmigiero 		break;
680e81a9076SMaciej S. Szmigiero 	}
681e81a9076SMaciej S. Szmigiero 
682e81a9076SMaciej S. Szmigiero 	CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_DCMODE_MASK, voutctrl,
683e81a9076SMaciej S. Szmigiero 				2, 0, CX25840_VCONFIG_DCMODE_BYTES);
684e81a9076SMaciej S. Szmigiero 	CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_IDID0S_MASK, voutctrl,
685e81a9076SMaciej S. Szmigiero 				2, 1, CX25840_VCONFIG_IDID0S_LINECNT);
686e81a9076SMaciej S. Szmigiero 	CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_VIPCLAMP_MASK, voutctrl,
687e81a9076SMaciej S. Szmigiero 				2, 4, CX25840_VCONFIG_VIPCLAMP_ENABLED);
688e81a9076SMaciej S. Szmigiero 
689e81a9076SMaciej S. Szmigiero 	for (i = 0; i < 3; i++)
690e81a9076SMaciej S. Szmigiero 		cx25840_write(client, 0x404 + i, voutctrl[i]);
691e81a9076SMaciej S. Szmigiero }
692e81a9076SMaciej S. Szmigiero 
cx25840_initialize(struct i2c_client * client)69389fc4eb9SHans Verkuil static void cx25840_initialize(struct i2c_client *client)
694bd985160SHans Verkuil {
69521340ae0SHans Verkuil 	DEFINE_WAIT(wait);
6969357b31cSHans Verkuil 	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
69721340ae0SHans Verkuil 	struct workqueue_struct *q;
698bd985160SHans Verkuil 
699bd985160SHans Verkuil 	/* datasheet startup in numbered steps, refer to page 3-77 */
700bd985160SHans Verkuil 	/* 2. */
701bd985160SHans Verkuil 	cx25840_and_or(client, 0x803, ~0x10, 0x00);
70210a34367SMauro Carvalho Chehab 	/*
70310a34367SMauro Carvalho Chehab 	 * The default of this register should be 4, but I get 0 instead.
70410a34367SMauro Carvalho Chehab 	 * Set this register to 4 manually.
70510a34367SMauro Carvalho Chehab 	 */
706bd985160SHans Verkuil 	cx25840_write(client, 0x000, 0x04);
707bd985160SHans Verkuil 	/* 3. */
708bd985160SHans Verkuil 	init_dll1(client);
709bd985160SHans Verkuil 	init_dll2(client);
710bd985160SHans Verkuil 	cx25840_write(client, 0x136, 0x0a);
711bd985160SHans Verkuil 	/* 4. */
712bd985160SHans Verkuil 	cx25840_write(client, 0x13c, 0x01);
713bd985160SHans Verkuil 	cx25840_write(client, 0x13c, 0x00);
714bd985160SHans Verkuil 	/* 5. */
71510a34367SMauro Carvalho Chehab 	/*
71610a34367SMauro Carvalho Chehab 	 * Do the firmware load in a work handler to prevent.
71710a34367SMauro Carvalho Chehab 	 * Otherwise the kernel is blocked waiting for the
71810a34367SMauro Carvalho Chehab 	 * bit-banging i2c interface to finish uploading the
71910a34367SMauro Carvalho Chehab 	 * firmware.
72010a34367SMauro Carvalho Chehab 	 */
72121340ae0SHans Verkuil 	INIT_WORK(&state->fw_work, cx25840_work_handler);
72221340ae0SHans Verkuil 	init_waitqueue_head(&state->fw_wait);
72321340ae0SHans Verkuil 	q = create_singlethread_workqueue("cx25840_fw");
72435378ce1SPan Bian 	if (q) {
72521340ae0SHans Verkuil 		prepare_to_wait(&state->fw_wait, &wait, TASK_UNINTERRUPTIBLE);
72621340ae0SHans Verkuil 		queue_work(q, &state->fw_work);
72721340ae0SHans Verkuil 		schedule();
72821340ae0SHans Verkuil 		finish_wait(&state->fw_wait, &wait);
72921340ae0SHans Verkuil 		destroy_workqueue(q);
73035378ce1SPan Bian 	}
73121340ae0SHans Verkuil 
732bd985160SHans Verkuil 	/* 6. */
733bd985160SHans Verkuil 	cx25840_write(client, 0x115, 0x8c);
734bd985160SHans Verkuil 	cx25840_write(client, 0x116, 0x07);
735bd985160SHans Verkuil 	cx25840_write(client, 0x118, 0x02);
736bd985160SHans Verkuil 	/* 7. */
737bd985160SHans Verkuil 	cx25840_write(client, 0x4a5, 0x80);
738bd985160SHans Verkuil 	cx25840_write(client, 0x4a5, 0x00);
739bd985160SHans Verkuil 	cx25840_write(client, 0x402, 0x00);
740bd985160SHans Verkuil 	/* 8. */
74173dcddc5SHans Verkuil 	cx25840_and_or(client, 0x401, ~0x18, 0);
74273dcddc5SHans Verkuil 	cx25840_and_or(client, 0x4a2, ~0x10, 0x10);
74373dcddc5SHans Verkuil 	/* steps 8c and 8d are done in change_input() */
744bd985160SHans Verkuil 	/* 10. */
745bd985160SHans Verkuil 	cx25840_write(client, 0x8d3, 0x1f);
746bd985160SHans Verkuil 	cx25840_write(client, 0x8e3, 0x03);
747bd985160SHans Verkuil 
748cb5aa1c6SHans Verkuil 	cx25840_std_setup(client);
749bd985160SHans Verkuil 
750bd985160SHans Verkuil 	/* trial and error says these are needed to get audio */
751bd985160SHans Verkuil 	cx25840_write(client, 0x914, 0xa0);
752bd985160SHans Verkuil 	cx25840_write(client, 0x918, 0xa0);
753bd985160SHans Verkuil 	cx25840_write(client, 0x919, 0x01);
754bd985160SHans Verkuil 
75525985edcSLucas De Marchi 	/* stereo preferred */
756bd985160SHans Verkuil 	cx25840_write(client, 0x809, 0x04);
757bd985160SHans Verkuil 	/* AC97 shift */
758bd985160SHans Verkuil 	cx25840_write(client, 0x8cf, 0x0f);
759bd985160SHans Verkuil 
760a8bbf12aSHans Verkuil 	/* (re)set input */
761a8bbf12aSHans Verkuil 	set_input(client, state->vid_input, state->aud_input);
762bd985160SHans Verkuil 
763e81a9076SMaciej S. Szmigiero 	if (state->generic_mode)
764e81a9076SMaciej S. Szmigiero 		cx25840_vconfig_apply(client);
765e81a9076SMaciej S. Szmigiero 
766bd985160SHans Verkuil 	/* start microcontroller */
767bd985160SHans Verkuil 	cx25840_and_or(client, 0x803, ~0x10, 0x10);
768bd985160SHans Verkuil }
769bd985160SHans Verkuil 
cx23885_initialize(struct i2c_client * client)770f234081bSSteven Toth static void cx23885_initialize(struct i2c_client *client)
771f234081bSSteven Toth {
772f234081bSSteven Toth 	DEFINE_WAIT(wait);
7739357b31cSHans Verkuil 	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
7743ee9bc12SBrad Love 	u32 clk_freq = 0;
775f234081bSSteven Toth 	struct workqueue_struct *q;
776f234081bSSteven Toth 
7773ee9bc12SBrad Love 	/* cx23885 sets hostdata to clk_freq pointer */
7783ee9bc12SBrad Love 	if (v4l2_get_subdev_hostdata(&state->sd))
7793ee9bc12SBrad Love 		clk_freq = *((u32 *)v4l2_get_subdev_hostdata(&state->sd));
7803ee9bc12SBrad Love 
781e283d780SAndy Walls 	/*
782e283d780SAndy Walls 	 * Come out of digital power down
783e283d780SAndy Walls 	 * The CX23888, at least, needs this, otherwise registers aside from
784e283d780SAndy Walls 	 * 0x0-0x2 can't be read or written.
785e283d780SAndy Walls 	 */
786e283d780SAndy Walls 	cx25840_write(client, 0x000, 0);
787e283d780SAndy Walls 
788f234081bSSteven Toth 	/* Internal Reset */
789f234081bSSteven Toth 	cx25840_and_or(client, 0x102, ~0x01, 0x01);
790f234081bSSteven Toth 	cx25840_and_or(client, 0x102, ~0x01, 0x00);
791f234081bSSteven Toth 
792f234081bSSteven Toth 	/* Stop microcontroller */
793f234081bSSteven Toth 	cx25840_and_or(client, 0x803, ~0x10, 0x00);
794f234081bSSteven Toth 
795f234081bSSteven Toth 	/* DIF in reset? */
796f234081bSSteven Toth 	cx25840_write(client, 0x398, 0);
797f234081bSSteven Toth 
798e283d780SAndy Walls 	/*
799e283d780SAndy Walls 	 * Trust the default xtal, no division
800e283d780SAndy Walls 	 * '885: 28.636363... MHz
801e283d780SAndy Walls 	 * '887: 25.000000 MHz
802e283d780SAndy Walls 	 * '888: 50.000000 MHz
803e283d780SAndy Walls 	 */
804f234081bSSteven Toth 	cx25840_write(client, 0x2, 0x76);
805f234081bSSteven Toth 
806e283d780SAndy Walls 	/* Power up all the PLL's and DLL */
807f234081bSSteven Toth 	cx25840_write(client, 0x1, 0x40);
808f234081bSSteven Toth 
809e283d780SAndy Walls 	/* Sys PLL */
810e283d780SAndy Walls 	switch (state->id) {
81129d6a98bSHans Verkuil 	case CX23888_AV:
812e283d780SAndy Walls 		/*
813e283d780SAndy Walls 		 * 50.0 MHz * (0xb + 0xe8ba26/0x2000000)/4 = 5 * 28.636363 MHz
814e283d780SAndy Walls 		 * 572.73 MHz before post divide
815e283d780SAndy Walls 		 */
8163ee9bc12SBrad Love 		if (clk_freq == 25000000) {
8173ee9bc12SBrad Love 			/* 888/ImpactVCBe or 25Mhz xtal */
8183ee9bc12SBrad Love 			; /* nothing to do */
8193ee9bc12SBrad Love 		} else {
82074900b47SSteven Toth 			/* HVR1850 or 50MHz xtal */
82174900b47SSteven Toth 			cx25840_write(client, 0x2, 0x71);
8223ee9bc12SBrad Love 		}
82374900b47SSteven Toth 		cx25840_write4(client, 0x11c, 0x01d1744c);
82474900b47SSteven Toth 		cx25840_write4(client, 0x118, 0x00000416);
82574900b47SSteven Toth 		cx25840_write4(client, 0x404, 0x0010253e);
82674900b47SSteven Toth 		cx25840_write4(client, 0x42c, 0x42600000);
82774900b47SSteven Toth 		cx25840_write4(client, 0x44c, 0x161f1000);
828e283d780SAndy Walls 		break;
82929d6a98bSHans Verkuil 	case CX23887_AV:
830e283d780SAndy Walls 		/*
831e283d780SAndy Walls 		 * 25.0 MHz * (0x16 + 0x1d1744c/0x2000000)/4 = 5 * 28.636363 MHz
832e283d780SAndy Walls 		 * 572.73 MHz before post divide
833e283d780SAndy Walls 		 */
834f234081bSSteven Toth 		cx25840_write4(client, 0x11c, 0x01d1744c);
835f234081bSSteven Toth 		cx25840_write4(client, 0x118, 0x00000416);
836e283d780SAndy Walls 		break;
83729d6a98bSHans Verkuil 	case CX23885_AV:
838e283d780SAndy Walls 	default:
839e283d780SAndy Walls 		/*
840e283d780SAndy Walls 		 * 28.636363 MHz * (0x14 + 0x0/0x2000000)/4 = 5 * 28.636363 MHz
841e283d780SAndy Walls 		 * 572.73 MHz before post divide
842e283d780SAndy Walls 		 */
843e283d780SAndy Walls 		cx25840_write4(client, 0x11c, 0x00000000);
844e283d780SAndy Walls 		cx25840_write4(client, 0x118, 0x00000414);
845e283d780SAndy Walls 		break;
846e283d780SAndy Walls 	}
847f234081bSSteven Toth 
848f234081bSSteven Toth 	/* Disable DIF bypass */
849f234081bSSteven Toth 	cx25840_write4(client, 0x33c, 0x00000001);
850f234081bSSteven Toth 
851f234081bSSteven Toth 	/* DIF Src phase inc */
852f234081bSSteven Toth 	cx25840_write4(client, 0x340, 0x0df7df83);
853f234081bSSteven Toth 
854e283d780SAndy Walls 	/*
855e283d780SAndy Walls 	 * Vid PLL
856e283d780SAndy Walls 	 * Setup for a BT.656 pixel clock of 13.5 Mpixels/second
857e283d780SAndy Walls 	 *
858e283d780SAndy Walls 	 * 28.636363 MHz * (0xf + 0x02be2c9/0x2000000)/4 = 8 * 13.5 MHz
859e283d780SAndy Walls 	 * 432.0 MHz before post divide
860e283d780SAndy Walls 	 */
86174900b47SSteven Toth 
86274900b47SSteven Toth 	/* HVR1850 */
86374900b47SSteven Toth 	switch (state->id) {
86429d6a98bSHans Verkuil 	case CX23888_AV:
8653ee9bc12SBrad Love 		if (clk_freq == 25000000) {
8663ee9bc12SBrad Love 			/* 888/ImpactVCBe or 25MHz xtal */
8673ee9bc12SBrad Love 			cx25840_write4(client, 0x10c, 0x01b6db7b);
8683ee9bc12SBrad Love 			cx25840_write4(client, 0x108, 0x00000512);
8693ee9bc12SBrad Love 		} else {
8703ee9bc12SBrad Love 			/* 888/HVR1250 or 50MHz xtal */
87174900b47SSteven Toth 			cx25840_write4(client, 0x10c, 0x13333333);
87274900b47SSteven Toth 			cx25840_write4(client, 0x108, 0x00000515);
8733ee9bc12SBrad Love 		}
87474900b47SSteven Toth 		break;
87574900b47SSteven Toth 	default:
876e283d780SAndy Walls 		cx25840_write4(client, 0x10c, 0x002be2c9);
877e283d780SAndy Walls 		cx25840_write4(client, 0x108, 0x0000040f);
87874900b47SSteven Toth 	}
879f234081bSSteven Toth 
880f234081bSSteven Toth 	/* Luma */
881f234081bSSteven Toth 	cx25840_write4(client, 0x414, 0x00107d12);
882f234081bSSteven Toth 
883f234081bSSteven Toth 	/* Chroma */
884ee61cd9fSHans Verkuil 	if (is_cx23888(state))
885ee61cd9fSHans Verkuil 		cx25840_write4(client, 0x418, 0x1d008282);
886ee61cd9fSHans Verkuil 	else
887f234081bSSteven Toth 		cx25840_write4(client, 0x420, 0x3d008282);
888f234081bSSteven Toth 
889e283d780SAndy Walls 	/*
890e283d780SAndy Walls 	 * Aux PLL
891e283d780SAndy Walls 	 * Initial setup for audio sample clock:
892e283d780SAndy Walls 	 * 48 ksps, 16 bits/sample, x160 multiplier = 122.88 MHz
89325985edcSLucas De Marchi 	 * Initial I2S output/master clock(?):
894e283d780SAndy Walls 	 * 48 ksps, 16 bits/sample, x16 multiplier = 12.288 MHz
895e283d780SAndy Walls 	 */
896e283d780SAndy Walls 	switch (state->id) {
89729d6a98bSHans Verkuil 	case CX23888_AV:
898e283d780SAndy Walls 		/*
899e283d780SAndy Walls 		 * 50.0 MHz * (0x7 + 0x0bedfa4/0x2000000)/3 = 122.88 MHz
900e283d780SAndy Walls 		 * 368.64 MHz before post divide
901e283d780SAndy Walls 		 * 122.88 MHz / 0xa = 12.288 MHz
902e283d780SAndy Walls 		 */
9033ee9bc12SBrad Love 		/* HVR1850 or 50MHz xtal or 25MHz xtal */
90474900b47SSteven Toth 		cx25840_write4(client, 0x114, 0x017dbf48);
90574900b47SSteven Toth 		cx25840_write4(client, 0x110, 0x000a030e);
906e283d780SAndy Walls 		break;
90729d6a98bSHans Verkuil 	case CX23887_AV:
908e283d780SAndy Walls 		/*
909e283d780SAndy Walls 		 * 25.0 MHz * (0xe + 0x17dbf48/0x2000000)/3 = 122.88 MHz
910e283d780SAndy Walls 		 * 368.64 MHz before post divide
911e283d780SAndy Walls 		 * 122.88 MHz / 0xa = 12.288 MHz
912e283d780SAndy Walls 		 */
913f234081bSSteven Toth 		cx25840_write4(client, 0x114, 0x017dbf48);
914f234081bSSteven Toth 		cx25840_write4(client, 0x110, 0x000a030e);
915e283d780SAndy Walls 		break;
91629d6a98bSHans Verkuil 	case CX23885_AV:
917e283d780SAndy Walls 	default:
918e283d780SAndy Walls 		/*
919e283d780SAndy Walls 		 * 28.636363 MHz * (0xc + 0x1bf0c9e/0x2000000)/3 = 122.88 MHz
920e283d780SAndy Walls 		 * 368.64 MHz before post divide
921e283d780SAndy Walls 		 * 122.88 MHz / 0xa = 12.288 MHz
922e283d780SAndy Walls 		 */
923e283d780SAndy Walls 		cx25840_write4(client, 0x114, 0x01bf0c9e);
924e283d780SAndy Walls 		cx25840_write4(client, 0x110, 0x000a030c);
925e283d780SAndy Walls 		break;
926c2c1b415SPeter Senna Tschudin 	}
927f234081bSSteven Toth 
928f234081bSSteven Toth 	/* ADC2 input select */
929f234081bSSteven Toth 	cx25840_write(client, 0x102, 0x10);
930f234081bSSteven Toth 
931f234081bSSteven Toth 	/* VIN1 & VIN5 */
932f234081bSSteven Toth 	cx25840_write(client, 0x103, 0x11);
933f234081bSSteven Toth 
934f234081bSSteven Toth 	/* Enable format auto detect */
935f234081bSSteven Toth 	cx25840_write(client, 0x400, 0);
936f234081bSSteven Toth 	/* Fast subchroma lock */
937f234081bSSteven Toth 	/* White crush, Chroma AGC & Chroma Killer enabled */
938f234081bSSteven Toth 	cx25840_write(client, 0x401, 0xe8);
939f234081bSSteven Toth 
940f234081bSSteven Toth 	/* Select AFE clock pad output source */
941f234081bSSteven Toth 	cx25840_write(client, 0x144, 0x05);
942f234081bSSteven Toth 
943f3d6f633SSteven Toth 	/* Drive GPIO2 direction and values for HVR1700
944f3d6f633SSteven Toth 	 * where an onboard mux selects the output of demodulator
945f3d6f633SSteven Toth 	 * vs the 417. Failure to set this results in no DTV.
946f3d6f633SSteven Toth 	 * It's safe to set this across all Hauppauge boards
947f3d6f633SSteven Toth 	 * currently, regardless of the board type.
948f3d6f633SSteven Toth 	 */
949f3d6f633SSteven Toth 	cx25840_write(client, 0x160, 0x1d);
950f3d6f633SSteven Toth 	cx25840_write(client, 0x164, 0x00);
951f3d6f633SSteven Toth 
95210a34367SMauro Carvalho Chehab 	/*
95310a34367SMauro Carvalho Chehab 	 * Do the firmware load in a work handler to prevent.
95410a34367SMauro Carvalho Chehab 	 * Otherwise the kernel is blocked waiting for the
95510a34367SMauro Carvalho Chehab 	 * bit-banging i2c interface to finish uploading the
95610a34367SMauro Carvalho Chehab 	 * firmware.
95710a34367SMauro Carvalho Chehab 	 */
958f234081bSSteven Toth 	INIT_WORK(&state->fw_work, cx25840_work_handler);
959f234081bSSteven Toth 	init_waitqueue_head(&state->fw_wait);
960f234081bSSteven Toth 	q = create_singlethread_workqueue("cx25840_fw");
96135378ce1SPan Bian 	if (q) {
962f234081bSSteven Toth 		prepare_to_wait(&state->fw_wait, &wait, TASK_UNINTERRUPTIBLE);
963f234081bSSteven Toth 		queue_work(q, &state->fw_work);
964f234081bSSteven Toth 		schedule();
965f234081bSSteven Toth 		finish_wait(&state->fw_wait, &wait);
966f234081bSSteven Toth 		destroy_workqueue(q);
96735378ce1SPan Bian 	}
968f234081bSSteven Toth 
96910a34367SMauro Carvalho Chehab 	/*
97010a34367SMauro Carvalho Chehab 	 * Call the cx23888 specific std setup func, we no longer rely on
97174900b47SSteven Toth 	 * the generic cx24840 func.
97274900b47SSteven Toth 	 */
973ba50e7e1SDevin Heitmueller 	if (is_cx23888(state))
974ba50e7e1SDevin Heitmueller 		cx23888_std_setup(client);
975ba50e7e1SDevin Heitmueller 	else
976ba50e7e1SDevin Heitmueller 		cx25840_std_setup(client);
977f234081bSSteven Toth 
978f234081bSSteven Toth 	/* (re)set input */
979f234081bSSteven Toth 	set_input(client, state->vid_input, state->aud_input);
980f234081bSSteven Toth 
981f234081bSSteven Toth 	/* start microcontroller */
982f234081bSSteven Toth 	cx25840_and_or(client, 0x803, ~0x10, 0x10);
98352fd3ddaSAndy Walls 
98452fd3ddaSAndy Walls 	/* Disable and clear video interrupts - we don't use them */
98552fd3ddaSAndy Walls 	cx25840_write4(client, CX25840_VID_INT_STAT_REG, 0xffffffff);
98652fd3ddaSAndy Walls 
98752fd3ddaSAndy Walls 	/* Disable and clear audio interrupts - we don't use them */
98852fd3ddaSAndy Walls 	cx25840_write(client, CX25840_AUD_INT_CTRL_REG, 0xff);
98952fd3ddaSAndy Walls 	cx25840_write(client, CX25840_AUD_INT_STAT_REG, 0xff);
99074900b47SSteven Toth 
99174900b47SSteven Toth 	/* CC raw enable */
99210a34367SMauro Carvalho Chehab 
99310a34367SMauro Carvalho Chehab 	/*
99410a34367SMauro Carvalho Chehab 	 *  - VIP 1.1 control codes - 10bit, blue field enable.
99574900b47SSteven Toth 	 *  - enable raw data during vertical blanking.
99674900b47SSteven Toth 	 *  - enable ancillary Data insertion for 656 or VIP.
99774900b47SSteven Toth 	 */
99874900b47SSteven Toth 	cx25840_write4(client, 0x404, 0x0010253e);
99974900b47SSteven Toth 
1000038fd414SBrad Love 	/* CC on  - VBI_LINE_CTRL3, FLD_VBI_MD_LINE12 */
1001cdf472d3SHans Verkuil 	cx25840_write(client, state->vbi_regs_offset + 0x42f, 0x66);
100274900b47SSteven Toth 
100374900b47SSteven Toth 	/* HVR-1250 / HVR1850 DIF related */
100474900b47SSteven Toth 	/* Power everything up */
100574900b47SSteven Toth 	cx25840_write4(client, 0x130, 0x0);
100674900b47SSteven Toth 
1007038fd414SBrad Love 	/* SRC_COMB_CFG */
1008ee61cd9fSHans Verkuil 	if (is_cx23888(state))
1009ee61cd9fSHans Verkuil 		cx25840_write4(client, 0x454, 0x6628021F);
1010ee61cd9fSHans Verkuil 	else
101174900b47SSteven Toth 		cx25840_write4(client, 0x478, 0x6628021F);
101274900b47SSteven Toth 
101374900b47SSteven Toth 	/* AFE_CLK_OUT_CTRL - Select the clock output source as output */
101474900b47SSteven Toth 	cx25840_write4(client, 0x144, 0x5);
101574900b47SSteven Toth 
101674900b47SSteven Toth 	/* I2C_OUT_CTL - I2S output configuration as
101774900b47SSteven Toth 	 * Master, Sony, Left justified, left sample on WS=1
101874900b47SSteven Toth 	 */
101974900b47SSteven Toth 	cx25840_write4(client, 0x918, 0x1a0);
102074900b47SSteven Toth 
102174900b47SSteven Toth 	/* AFE_DIAG_CTRL1 */
102274900b47SSteven Toth 	cx25840_write4(client, 0x134, 0x000a1800);
102374900b47SSteven Toth 
102474900b47SSteven Toth 	/* AFE_DIAG_CTRL3 - Inverted Polarity for Audio and Video */
102574900b47SSteven Toth 	cx25840_write4(client, 0x13c, 0x00310000);
1026f234081bSSteven Toth }
1027f234081bSSteven Toth 
1028bd985160SHans Verkuil /* ----------------------------------------------------------------------- */
1029bd985160SHans Verkuil 
cx231xx_initialize(struct i2c_client * client)1030149783b5SSri Deevi static void cx231xx_initialize(struct i2c_client *client)
1031149783b5SSri Deevi {
1032149783b5SSri Deevi 	DEFINE_WAIT(wait);
1033149783b5SSri Deevi 	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
1034149783b5SSri Deevi 	struct workqueue_struct *q;
1035149783b5SSri Deevi 
1036149783b5SSri Deevi 	/* Internal Reset */
1037149783b5SSri Deevi 	cx25840_and_or(client, 0x102, ~0x01, 0x01);
1038149783b5SSri Deevi 	cx25840_and_or(client, 0x102, ~0x01, 0x00);
1039149783b5SSri Deevi 
1040149783b5SSri Deevi 	/* Stop microcontroller */
1041149783b5SSri Deevi 	cx25840_and_or(client, 0x803, ~0x10, 0x00);
1042149783b5SSri Deevi 
1043149783b5SSri Deevi 	/* DIF in reset? */
1044149783b5SSri Deevi 	cx25840_write(client, 0x398, 0);
1045149783b5SSri Deevi 
1046149783b5SSri Deevi 	/* Trust the default xtal, no division */
1047149783b5SSri Deevi 	/* This changes for the cx23888 products */
1048149783b5SSri Deevi 	cx25840_write(client, 0x2, 0x76);
1049149783b5SSri Deevi 
1050149783b5SSri Deevi 	/* Bring down the regulator for AUX clk */
1051149783b5SSri Deevi 	cx25840_write(client, 0x1, 0x40);
1052149783b5SSri Deevi 
1053149783b5SSri Deevi 	/* Disable DIF bypass */
1054149783b5SSri Deevi 	cx25840_write4(client, 0x33c, 0x00000001);
1055149783b5SSri Deevi 
1056149783b5SSri Deevi 	/* DIF Src phase inc */
1057149783b5SSri Deevi 	cx25840_write4(client, 0x340, 0x0df7df83);
1058149783b5SSri Deevi 
1059149783b5SSri Deevi 	/* Luma */
1060149783b5SSri Deevi 	cx25840_write4(client, 0x414, 0x00107d12);
1061149783b5SSri Deevi 
1062149783b5SSri Deevi 	/* Chroma */
1063149783b5SSri Deevi 	cx25840_write4(client, 0x420, 0x3d008282);
1064149783b5SSri Deevi 
1065149783b5SSri Deevi 	/* ADC2 input select */
1066149783b5SSri Deevi 	cx25840_write(client, 0x102, 0x10);
1067149783b5SSri Deevi 
1068149783b5SSri Deevi 	/* VIN1 & VIN5 */
1069149783b5SSri Deevi 	cx25840_write(client, 0x103, 0x11);
1070149783b5SSri Deevi 
1071149783b5SSri Deevi 	/* Enable format auto detect */
1072149783b5SSri Deevi 	cx25840_write(client, 0x400, 0);
1073149783b5SSri Deevi 	/* Fast subchroma lock */
1074149783b5SSri Deevi 	/* White crush, Chroma AGC & Chroma Killer enabled */
1075149783b5SSri Deevi 	cx25840_write(client, 0x401, 0xe8);
1076149783b5SSri Deevi 
107710a34367SMauro Carvalho Chehab 	/*
107810a34367SMauro Carvalho Chehab 	 * Do the firmware load in a work handler to prevent.
107910a34367SMauro Carvalho Chehab 	 * Otherwise the kernel is blocked waiting for the
108010a34367SMauro Carvalho Chehab 	 * bit-banging i2c interface to finish uploading the
108110a34367SMauro Carvalho Chehab 	 * firmware.
108210a34367SMauro Carvalho Chehab 	 */
1083149783b5SSri Deevi 	INIT_WORK(&state->fw_work, cx25840_work_handler);
1084149783b5SSri Deevi 	init_waitqueue_head(&state->fw_wait);
1085149783b5SSri Deevi 	q = create_singlethread_workqueue("cx25840_fw");
108635378ce1SPan Bian 	if (q) {
1087149783b5SSri Deevi 		prepare_to_wait(&state->fw_wait, &wait, TASK_UNINTERRUPTIBLE);
1088149783b5SSri Deevi 		queue_work(q, &state->fw_work);
1089149783b5SSri Deevi 		schedule();
1090149783b5SSri Deevi 		finish_wait(&state->fw_wait, &wait);
1091149783b5SSri Deevi 		destroy_workqueue(q);
109235378ce1SPan Bian 	}
1093149783b5SSri Deevi 
1094149783b5SSri Deevi 	cx25840_std_setup(client);
1095149783b5SSri Deevi 
1096149783b5SSri Deevi 	/* (re)set input */
1097149783b5SSri Deevi 	set_input(client, state->vid_input, state->aud_input);
1098149783b5SSri Deevi 
1099149783b5SSri Deevi 	/* start microcontroller */
1100149783b5SSri Deevi 	cx25840_and_or(client, 0x803, ~0x10, 0x10);
110199d38909SSteven Toth 
110299d38909SSteven Toth 	/* CC raw enable */
110399d38909SSteven Toth 	cx25840_write(client, 0x404, 0x0b);
110499d38909SSteven Toth 
110599d38909SSteven Toth 	/* CC on */
110699d38909SSteven Toth 	cx25840_write(client, 0x42f, 0x66);
110799d38909SSteven Toth 	cx25840_write4(client, 0x474, 0x1e1e601a);
1108149783b5SSri Deevi }
1109149783b5SSri Deevi 
1110149783b5SSri Deevi /* ----------------------------------------------------------------------- */
1111149783b5SSri Deevi 
cx25840_std_setup(struct i2c_client * client)1112cb5aa1c6SHans Verkuil void cx25840_std_setup(struct i2c_client *client)
1113cb5aa1c6SHans Verkuil {
11149357b31cSHans Verkuil 	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
1115cb5aa1c6SHans Verkuil 	v4l2_std_id std = state->std;
1116cb5aa1c6SHans Verkuil 	int hblank, hactive, burst, vblank, vactive, sc;
1117cb5aa1c6SHans Verkuil 	int vblank656, src_decimation;
1118cb5aa1c6SHans Verkuil 	int luma_lpf, uv_lpf, comb;
1119cb5aa1c6SHans Verkuil 	u32 pll_int, pll_frac, pll_post;
1120cb5aa1c6SHans Verkuil 
1121cb5aa1c6SHans Verkuil 	/* datasheet startup, step 8d */
1122cb5aa1c6SHans Verkuil 	if (std & ~V4L2_STD_NTSC)
1123cb5aa1c6SHans Verkuil 		cx25840_write(client, 0x49f, 0x11);
1124cb5aa1c6SHans Verkuil 	else
1125cb5aa1c6SHans Verkuil 		cx25840_write(client, 0x49f, 0x14);
1126cb5aa1c6SHans Verkuil 
1127e81a9076SMaciej S. Szmigiero 	/* generic mode uses the values that the chip autoconfig would set */
1128cb5aa1c6SHans Verkuil 	if (std & V4L2_STD_625_50) {
1129cb5aa1c6SHans Verkuil 		hblank = 132;
1130cb5aa1c6SHans Verkuil 		hactive = 720;
1131cb5aa1c6SHans Verkuil 		burst = 93;
1132e81a9076SMaciej S. Szmigiero 		if (state->generic_mode) {
1133e81a9076SMaciej S. Szmigiero 			vblank = 34;
1134e81a9076SMaciej S. Szmigiero 			vactive = 576;
1135e81a9076SMaciej S. Szmigiero 			vblank656 = 38;
1136e81a9076SMaciej S. Szmigiero 		} else {
1137cb5aa1c6SHans Verkuil 			vblank = 36;
1138cb5aa1c6SHans Verkuil 			vactive = 580;
1139cb5aa1c6SHans Verkuil 			vblank656 = 40;
1140e81a9076SMaciej S. Szmigiero 		}
1141cb5aa1c6SHans Verkuil 		src_decimation = 0x21f;
1142cb5aa1c6SHans Verkuil 		luma_lpf = 2;
1143cb5aa1c6SHans Verkuil 
1144cb5aa1c6SHans Verkuil 		if (std & V4L2_STD_SECAM) {
1145cb5aa1c6SHans Verkuil 			uv_lpf = 0;
1146cb5aa1c6SHans Verkuil 			comb = 0;
1147cb5aa1c6SHans Verkuil 			sc = 0x0a425f;
1148cb5aa1c6SHans Verkuil 		} else if (std == V4L2_STD_PAL_Nc) {
1149e81a9076SMaciej S. Szmigiero 			if (state->generic_mode) {
1150e81a9076SMaciej S. Szmigiero 				burst = 95;
1151e81a9076SMaciej S. Szmigiero 				luma_lpf = 1;
1152e81a9076SMaciej S. Szmigiero 			}
1153cb5aa1c6SHans Verkuil 			uv_lpf = 1;
1154cb5aa1c6SHans Verkuil 			comb = 0x20;
1155cb5aa1c6SHans Verkuil 			sc = 556453;
1156cb5aa1c6SHans Verkuil 		} else {
1157cb5aa1c6SHans Verkuil 			uv_lpf = 1;
1158cb5aa1c6SHans Verkuil 			comb = 0x20;
1159cb5aa1c6SHans Verkuil 			sc = 688739;
1160cb5aa1c6SHans Verkuil 		}
1161cb5aa1c6SHans Verkuil 	} else {
1162cb5aa1c6SHans Verkuil 		hactive = 720;
1163cb5aa1c6SHans Verkuil 		hblank = 122;
1164cb5aa1c6SHans Verkuil 		vactive = 487;
1165cb5aa1c6SHans Verkuil 		luma_lpf = 1;
1166cb5aa1c6SHans Verkuil 		uv_lpf = 1;
1167e81a9076SMaciej S. Szmigiero 		if (state->generic_mode) {
1168e81a9076SMaciej S. Szmigiero 			vblank = 20;
1169e81a9076SMaciej S. Szmigiero 			vblank656 = 24;
1170e81a9076SMaciej S. Szmigiero 		}
1171cb5aa1c6SHans Verkuil 
1172cb5aa1c6SHans Verkuil 		src_decimation = 0x21f;
1173cb5aa1c6SHans Verkuil 		if (std == V4L2_STD_PAL_60) {
1174e81a9076SMaciej S. Szmigiero 			if (!state->generic_mode) {
1175cb5aa1c6SHans Verkuil 				vblank = 26;
1176cb5aa1c6SHans Verkuil 				vblank656 = 26;
1177cb5aa1c6SHans Verkuil 				burst = 0x5b;
117810a34367SMauro Carvalho Chehab 			} else {
1179e81a9076SMaciej S. Szmigiero 				burst = 0x59;
118010a34367SMauro Carvalho Chehab 			}
1181cb5aa1c6SHans Verkuil 			luma_lpf = 2;
1182cb5aa1c6SHans Verkuil 			comb = 0x20;
1183cb5aa1c6SHans Verkuil 			sc = 688739;
1184cb5aa1c6SHans Verkuil 		} else if (std == V4L2_STD_PAL_M) {
1185cb5aa1c6SHans Verkuil 			vblank = 20;
1186cb5aa1c6SHans Verkuil 			vblank656 = 24;
1187cb5aa1c6SHans Verkuil 			burst = 0x61;
1188cb5aa1c6SHans Verkuil 			comb = 0x20;
1189cb5aa1c6SHans Verkuil 			sc = 555452;
1190cb5aa1c6SHans Verkuil 		} else {
1191e81a9076SMaciej S. Szmigiero 			if (!state->generic_mode) {
1192cb5aa1c6SHans Verkuil 				vblank = 26;
1193cb5aa1c6SHans Verkuil 				vblank656 = 26;
1194e81a9076SMaciej S. Szmigiero 			}
1195cb5aa1c6SHans Verkuil 			burst = 0x5b;
1196cb5aa1c6SHans Verkuil 			comb = 0x66;
1197cb5aa1c6SHans Verkuil 			sc = 556063;
1198cb5aa1c6SHans Verkuil 		}
1199cb5aa1c6SHans Verkuil 	}
1200cb5aa1c6SHans Verkuil 
1201cb5aa1c6SHans Verkuil 	/* DEBUG: Displays configured PLL frequency */
12022a03f034SAndy Walls 	if (!is_cx231xx(state)) {
1203cb5aa1c6SHans Verkuil 		pll_int = cx25840_read(client, 0x108);
1204cb5aa1c6SHans Verkuil 		pll_frac = cx25840_read4(client, 0x10c) & 0x1ffffff;
1205cb5aa1c6SHans Verkuil 		pll_post = cx25840_read(client, 0x109);
1206cb5aa1c6SHans Verkuil 		v4l_dbg(1, cx25840_debug, client,
1207cb5aa1c6SHans Verkuil 			"PLL regs = int: %u, frac: %u, post: %u\n",
1208cb5aa1c6SHans Verkuil 			pll_int, pll_frac, pll_post);
1209cb5aa1c6SHans Verkuil 
1210cb5aa1c6SHans Verkuil 		if (pll_post) {
1211cb5aa1c6SHans Verkuil 			int fin, fsc;
1212cb5aa1c6SHans Verkuil 			int pll = (28636363L * ((((u64)pll_int) << 25L) + pll_frac)) >> 25L;
1213cb5aa1c6SHans Verkuil 
1214cb5aa1c6SHans Verkuil 			pll /= pll_post;
121510a34367SMauro Carvalho Chehab 			v4l_dbg(1, cx25840_debug, client,
121610a34367SMauro Carvalho Chehab 				"PLL = %d.%06d MHz\n",
1217cb5aa1c6SHans Verkuil 				pll / 1000000, pll % 1000000);
121810a34367SMauro Carvalho Chehab 			v4l_dbg(1, cx25840_debug, client,
121910a34367SMauro Carvalho Chehab 				"PLL/8 = %d.%06d MHz\n",
1220cb5aa1c6SHans Verkuil 				pll / 8000000, (pll / 8) % 1000000);
1221cb5aa1c6SHans Verkuil 
1222cb5aa1c6SHans Verkuil 			fin = ((u64)src_decimation * pll) >> 12;
1223cb5aa1c6SHans Verkuil 			v4l_dbg(1, cx25840_debug, client,
1224cb5aa1c6SHans Verkuil 				"ADC Sampling freq = %d.%06d MHz\n",
1225cb5aa1c6SHans Verkuil 				fin / 1000000, fin % 1000000);
1226cb5aa1c6SHans Verkuil 
1227cb5aa1c6SHans Verkuil 			fsc = (((u64)sc) * pll) >> 24L;
1228cb5aa1c6SHans Verkuil 			v4l_dbg(1, cx25840_debug, client,
1229cb5aa1c6SHans Verkuil 				"Chroma sub-carrier freq = %d.%06d MHz\n",
1230cb5aa1c6SHans Verkuil 				fsc / 1000000, fsc % 1000000);
1231cb5aa1c6SHans Verkuil 
123210a34367SMauro Carvalho Chehab 			v4l_dbg(1, cx25840_debug, client,
123310a34367SMauro Carvalho Chehab 				"hblank %i, hactive %i, vblank %i, vactive %i, vblank656 %i, src_dec %i, burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x, sc 0x%06x\n",
1234cb5aa1c6SHans Verkuil 				hblank, hactive, vblank, vactive, vblank656,
123510a34367SMauro Carvalho Chehab 				src_decimation, burst, luma_lpf, uv_lpf,
123610a34367SMauro Carvalho Chehab 				comb, sc);
1237cb5aa1c6SHans Verkuil 		}
1238149783b5SSri Deevi 	}
1239cb5aa1c6SHans Verkuil 
1240cb5aa1c6SHans Verkuil 	/* Sets horizontal blanking delay and active lines */
1241cb5aa1c6SHans Verkuil 	cx25840_write(client, 0x470, hblank);
1242cb5aa1c6SHans Verkuil 	cx25840_write(client, 0x471,
124385273c38SJoe Perches 		      (((hblank >> 8) & 0x3) | (hactive << 4)) & 0xff);
1244cb5aa1c6SHans Verkuil 	cx25840_write(client, 0x472, hactive >> 4);
1245cb5aa1c6SHans Verkuil 
1246cb5aa1c6SHans Verkuil 	/* Sets burst gate delay */
1247cb5aa1c6SHans Verkuil 	cx25840_write(client, 0x473, burst);
1248cb5aa1c6SHans Verkuil 
1249cb5aa1c6SHans Verkuil 	/* Sets vertical blanking delay and active duration */
1250cb5aa1c6SHans Verkuil 	cx25840_write(client, 0x474, vblank);
1251cb5aa1c6SHans Verkuil 	cx25840_write(client, 0x475,
125285273c38SJoe Perches 		      (((vblank >> 8) & 0x3) | (vactive << 4)) & 0xff);
1253cb5aa1c6SHans Verkuil 	cx25840_write(client, 0x476, vactive >> 4);
1254cb5aa1c6SHans Verkuil 	cx25840_write(client, 0x477, vblank656);
1255cb5aa1c6SHans Verkuil 
1256cb5aa1c6SHans Verkuil 	/* Sets src decimation rate */
125785273c38SJoe Perches 	cx25840_write(client, 0x478, src_decimation & 0xff);
125885273c38SJoe Perches 	cx25840_write(client, 0x479, (src_decimation >> 8) & 0xff);
1259cb5aa1c6SHans Verkuil 
1260cb5aa1c6SHans Verkuil 	/* Sets Luma and UV Low pass filters */
1261cb5aa1c6SHans Verkuil 	cx25840_write(client, 0x47a, luma_lpf << 6 | ((uv_lpf << 4) & 0x30));
1262cb5aa1c6SHans Verkuil 
1263cb5aa1c6SHans Verkuil 	/* Enables comb filters */
1264cb5aa1c6SHans Verkuil 	cx25840_write(client, 0x47b, comb);
1265cb5aa1c6SHans Verkuil 
1266cb5aa1c6SHans Verkuil 	/* Sets SC Step*/
1267cb5aa1c6SHans Verkuil 	cx25840_write(client, 0x47c, sc);
126885273c38SJoe Perches 	cx25840_write(client, 0x47d, (sc >> 8) & 0xff);
126985273c38SJoe Perches 	cx25840_write(client, 0x47e, (sc >> 16) & 0xff);
1270cb5aa1c6SHans Verkuil 
1271cb5aa1c6SHans Verkuil 	/* Sets VBI parameters */
1272cb5aa1c6SHans Verkuil 	if (std & V4L2_STD_625_50) {
1273cb5aa1c6SHans Verkuil 		cx25840_write(client, 0x47f, 0x01);
1274cb5aa1c6SHans Verkuil 		state->vbi_line_offset = 5;
1275cb5aa1c6SHans Verkuil 	} else {
1276cb5aa1c6SHans Verkuil 		cx25840_write(client, 0x47f, 0x00);
1277cb5aa1c6SHans Verkuil 		state->vbi_line_offset = 8;
1278cb5aa1c6SHans Verkuil 	}
1279cb5aa1c6SHans Verkuil }
1280cb5aa1c6SHans Verkuil 
1281cb5aa1c6SHans Verkuil /* ----------------------------------------------------------------------- */
1282cb5aa1c6SHans Verkuil 
input_change(struct i2c_client * client)1283bd985160SHans Verkuil static void input_change(struct i2c_client *client)
1284bd985160SHans Verkuil {
12859357b31cSHans Verkuil 	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
1286081b496aSHans Verkuil 	v4l2_std_id std = state->std;
1287bd985160SHans Verkuil 
128873dcddc5SHans Verkuil 	/* Follow step 8c and 8d of section 3.16 in the cx25840 datasheet */
128973dcddc5SHans Verkuil 	if (std & V4L2_STD_SECAM) {
129073dcddc5SHans Verkuil 		cx25840_write(client, 0x402, 0);
129110a34367SMauro Carvalho Chehab 	} else {
129273dcddc5SHans Verkuil 		cx25840_write(client, 0x402, 0x04);
129310a34367SMauro Carvalho Chehab 		cx25840_write(client, 0x49f,
129410a34367SMauro Carvalho Chehab 			      (std & V4L2_STD_NTSC) ? 0x14 : 0x11);
129573dcddc5SHans Verkuil 	}
129673dcddc5SHans Verkuil 	cx25840_and_or(client, 0x401, ~0x60, 0);
129773dcddc5SHans Verkuil 	cx25840_and_or(client, 0x401, ~0x60, 0x60);
12985af79f86SSven Barth 
12995af79f86SSven Barth 	/* Don't write into audio registers on cx2583x chips */
13005af79f86SSven Barth 	if (is_cx2583x(state))
13015af79f86SSven Barth 		return;
13025af79f86SSven Barth 
130382677618SHans Verkuil 	cx25840_and_or(client, 0x810, ~0x01, 1);
130473dcddc5SHans Verkuil 
130539c4ad6aSHans Verkuil 	if (state->radio) {
130639c4ad6aSHans Verkuil 		cx25840_write(client, 0x808, 0xf9);
130739c4ad6aSHans Verkuil 		cx25840_write(client, 0x80b, 0x00);
130810a34367SMauro Carvalho Chehab 	} else if (std & V4L2_STD_525_60) {
130910a34367SMauro Carvalho Chehab 		/*
131010a34367SMauro Carvalho Chehab 		 * Certain Hauppauge PVR150 models have a hardware bug
131110a34367SMauro Carvalho Chehab 		 * that causes audio to drop out. For these models the
131210a34367SMauro Carvalho Chehab 		 * audio standard must be set explicitly.
131310a34367SMauro Carvalho Chehab 		 * To be precise: it affects cards with tuner models
131410a34367SMauro Carvalho Chehab 		 * 85, 99 and 112 (model numbers from tveeprom).
131510a34367SMauro Carvalho Chehab 		 */
1316d97a11e0SHans Verkuil 		int hw_fix = state->pvr150_workaround;
1317d97a11e0SHans Verkuil 
1318f95006f8SHans Verkuil 		if (std == V4L2_STD_NTSC_M_JP) {
1319f95006f8SHans Verkuil 			/* Japan uses EIAJ audio standard */
1320d97a11e0SHans Verkuil 			cx25840_write(client, 0x808, hw_fix ? 0x2f : 0xf7);
1321d97a11e0SHans Verkuil 		} else if (std == V4L2_STD_NTSC_M_KR) {
1322d97a11e0SHans Verkuil 			/* South Korea uses A2 audio standard */
1323d97a11e0SHans Verkuil 			cx25840_write(client, 0x808, hw_fix ? 0x3f : 0xf8);
1324f95006f8SHans Verkuil 		} else {
1325f95006f8SHans Verkuil 			/* Others use the BTSC audio standard */
1326d97a11e0SHans Verkuil 			cx25840_write(client, 0x808, hw_fix ? 0x1f : 0xf6);
1327f95006f8SHans Verkuil 		}
1328bd985160SHans Verkuil 		cx25840_write(client, 0x80b, 0x00);
1329839e4a4aSMauro Carvalho Chehab 	} else if (std & V4L2_STD_PAL) {
13303c3099d5SAleksandr V. Piskunov 		/* Autodetect audio standard and audio system */
1331839e4a4aSMauro Carvalho Chehab 		cx25840_write(client, 0x808, 0xff);
133210a34367SMauro Carvalho Chehab 		/*
133310a34367SMauro Carvalho Chehab 		 * Since system PAL-L is pretty much non-existent and
133410a34367SMauro Carvalho Chehab 		 * not used by any public broadcast network, force
133510a34367SMauro Carvalho Chehab 		 * 6.5 MHz carrier to be interpreted as System DK,
133610a34367SMauro Carvalho Chehab 		 * this avoids DK audio detection instability
133710a34367SMauro Carvalho Chehab 		 */
13383c3099d5SAleksandr V. Piskunov 		cx25840_write(client, 0x80b, 0x00);
1339839e4a4aSMauro Carvalho Chehab 	} else if (std & V4L2_STD_SECAM) {
13403c3099d5SAleksandr V. Piskunov 		/* Autodetect audio standard and audio system */
1341839e4a4aSMauro Carvalho Chehab 		cx25840_write(client, 0x808, 0xff);
134210a34367SMauro Carvalho Chehab 		/*
134310a34367SMauro Carvalho Chehab 		 * If only one of SECAM-DK / SECAM-L is required, then force
134410a34367SMauro Carvalho Chehab 		 * 6.5MHz carrier, else autodetect it
134510a34367SMauro Carvalho Chehab 		 */
13463c3099d5SAleksandr V. Piskunov 		if ((std & V4L2_STD_SECAM_DK) &&
13473c3099d5SAleksandr V. Piskunov 		    !(std & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC))) {
13483c3099d5SAleksandr V. Piskunov 			/* 6.5 MHz carrier to be interpreted as System DK */
13493c3099d5SAleksandr V. Piskunov 			cx25840_write(client, 0x80b, 0x00);
13503c3099d5SAleksandr V. Piskunov 		} else if (!(std & V4L2_STD_SECAM_DK) &&
13513c3099d5SAleksandr V. Piskunov 			   (std & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC))) {
13523c3099d5SAleksandr V. Piskunov 			/* 6.5 MHz carrier to be interpreted as System L */
13533c3099d5SAleksandr V. Piskunov 			cx25840_write(client, 0x80b, 0x08);
13543c3099d5SAleksandr V. Piskunov 		} else {
13553c3099d5SAleksandr V. Piskunov 			/* 6.5 MHz carrier to be autodetected */
1356839e4a4aSMauro Carvalho Chehab 			cx25840_write(client, 0x80b, 0x10);
1357bd985160SHans Verkuil 		}
13583c3099d5SAleksandr V. Piskunov 	}
1359bd985160SHans Verkuil 
136082677618SHans Verkuil 	cx25840_and_or(client, 0x810, ~0x01, 0);
1361bd985160SHans Verkuil }
1362bd985160SHans Verkuil 
set_input(struct i2c_client * client,enum cx25840_video_input vid_input,enum cx25840_audio_input aud_input)136310a34367SMauro Carvalho Chehab static int set_input(struct i2c_client *client,
136410a34367SMauro Carvalho Chehab 		     enum cx25840_video_input vid_input,
1365a8bbf12aSHans Verkuil 		     enum cx25840_audio_input aud_input)
1366bd985160SHans Verkuil {
13679357b31cSHans Verkuil 	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
1368a8bbf12aSHans Verkuil 	u8 is_composite = (vid_input >= CX25840_COMPOSITE1 &&
1369a8bbf12aSHans Verkuil 			   vid_input <= CX25840_COMPOSITE8);
1370fb29ab96SDavid T.L. Wong 	u8 is_component = (vid_input & CX25840_COMPONENT_ON) ==
1371fb29ab96SDavid T.L. Wong 			CX25840_COMPONENT_ON;
137274900b47SSteven Toth 	u8 is_dif = (vid_input & CX25840_DIF_ON) ==
137374900b47SSteven Toth 			CX25840_DIF_ON;
137474900b47SSteven Toth 	u8 is_svideo = (vid_input & CX25840_SVIDEO_ON) ==
137574900b47SSteven Toth 			CX25840_SVIDEO_ON;
1376fb29ab96SDavid T.L. Wong 	int luma = vid_input & 0xf0;
1377fb29ab96SDavid T.L. Wong 	int chroma = vid_input & 0xf00;
1378a8bbf12aSHans Verkuil 	u8 reg;
137974900b47SSteven Toth 	u32 val;
1380bd985160SHans Verkuil 
1381f234081bSSteven Toth 	v4l_dbg(1, cx25840_debug, client,
1382f234081bSSteven Toth 		"decoder set video input %d, audio input %d\n",
1383a8bbf12aSHans Verkuil 		vid_input, aud_input);
1384bd985160SHans Verkuil 
1385f234081bSSteven Toth 	if (vid_input >= CX25840_VIN1_CH1) {
1386f234081bSSteven Toth 		v4l_dbg(1, cx25840_debug, client, "vid_input 0x%x\n",
1387f234081bSSteven Toth 			vid_input);
1388f234081bSSteven Toth 		reg = vid_input & 0xff;
138910e43d90SKusanagi Kouichi 		is_composite = !is_component &&
139010e43d90SKusanagi Kouichi 			       ((vid_input & CX25840_SVIDEO_ON) != CX25840_SVIDEO_ON);
1391f234081bSSteven Toth 
1392f234081bSSteven Toth 		v4l_dbg(1, cx25840_debug, client, "mux cfg 0x%x comp=%d\n",
1393f234081bSSteven Toth 			reg, is_composite);
1394fb29ab96SDavid T.L. Wong 	} else if (is_composite) {
1395a8bbf12aSHans Verkuil 		reg = 0xf0 + (vid_input - CX25840_COMPOSITE1);
1396bd985160SHans Verkuil 	} else {
1397a8bbf12aSHans Verkuil 		if ((vid_input & ~0xff0) ||
139810a34367SMauro Carvalho Chehab 		    luma < CX25840_SVIDEO_LUMA1 ||
139910a34367SMauro Carvalho Chehab 		    luma > CX25840_SVIDEO_LUMA8 ||
140010a34367SMauro Carvalho Chehab 		    chroma < CX25840_SVIDEO_CHROMA4 ||
140110a34367SMauro Carvalho Chehab 		    chroma > CX25840_SVIDEO_CHROMA8) {
1402f234081bSSteven Toth 			v4l_err(client, "0x%04x is not a valid video input!\n",
1403f234081bSSteven Toth 				vid_input);
1404a8bbf12aSHans Verkuil 			return -EINVAL;
1405bd985160SHans Verkuil 		}
1406a8bbf12aSHans Verkuil 		reg = 0xf0 + ((luma - CX25840_SVIDEO_LUMA1) >> 4);
1407a8bbf12aSHans Verkuil 		if (chroma >= CX25840_SVIDEO_CHROMA7) {
1408a8bbf12aSHans Verkuil 			reg &= 0x3f;
1409a8bbf12aSHans Verkuil 			reg |= (chroma - CX25840_SVIDEO_CHROMA7) >> 2;
1410bd985160SHans Verkuil 		} else {
1411a8bbf12aSHans Verkuil 			reg &= 0xcf;
1412a8bbf12aSHans Verkuil 			reg |= (chroma - CX25840_SVIDEO_CHROMA4) >> 4;
1413a8bbf12aSHans Verkuil 		}
1414bd985160SHans Verkuil 	}
1415bd985160SHans Verkuil 
1416f234081bSSteven Toth 	/* The caller has previously prepared the correct routing
1417f234081bSSteven Toth 	 * configuration in reg (for the cx23885) so we have no
1418f234081bSSteven Toth 	 * need to attempt to flip bits for earlier av decoders.
1419f234081bSSteven Toth 	 */
14202a03f034SAndy Walls 	if (!is_cx2388x(state) && !is_cx231xx(state)) {
1421a8bbf12aSHans Verkuil 		switch (aud_input) {
1422a8bbf12aSHans Verkuil 		case CX25840_AUDIO_SERIAL:
1423a8bbf12aSHans Verkuil 			/* do nothing, use serial audio input */
1424bd985160SHans Verkuil 			break;
142510a34367SMauro Carvalho Chehab 		case CX25840_AUDIO4:
142610a34367SMauro Carvalho Chehab 			reg &= ~0x30;
142710a34367SMauro Carvalho Chehab 			break;
142810a34367SMauro Carvalho Chehab 		case CX25840_AUDIO5:
142910a34367SMauro Carvalho Chehab 			reg &= ~0x30;
143010a34367SMauro Carvalho Chehab 			reg |= 0x10;
143110a34367SMauro Carvalho Chehab 			break;
143210a34367SMauro Carvalho Chehab 		case CX25840_AUDIO6:
143310a34367SMauro Carvalho Chehab 			reg &= ~0x30;
143410a34367SMauro Carvalho Chehab 			reg |= 0x20;
143510a34367SMauro Carvalho Chehab 			break;
143610a34367SMauro Carvalho Chehab 		case CX25840_AUDIO7:
143710a34367SMauro Carvalho Chehab 			reg &= ~0xc0;
143810a34367SMauro Carvalho Chehab 			break;
143910a34367SMauro Carvalho Chehab 		case CX25840_AUDIO8:
144010a34367SMauro Carvalho Chehab 			reg &= ~0xc0;
144110a34367SMauro Carvalho Chehab 			reg |= 0x40;
144210a34367SMauro Carvalho Chehab 			break;
1443bd985160SHans Verkuil 		default:
1444f234081bSSteven Toth 			v4l_err(client, "0x%04x is not a valid audio input!\n",
1445f234081bSSteven Toth 				aud_input);
1446bd985160SHans Verkuil 			return -EINVAL;
1447bd985160SHans Verkuil 		}
1448f234081bSSteven Toth 	}
1449bd985160SHans Verkuil 
1450a8bbf12aSHans Verkuil 	cx25840_write(client, 0x103, reg);
1451f234081bSSteven Toth 
1452fb29ab96SDavid T.L. Wong 	/* Set INPUT_MODE to Composite, S-Video or Component */
1453fb29ab96SDavid T.L. Wong 	if (is_component)
1454fb29ab96SDavid T.L. Wong 		cx25840_and_or(client, 0x401, ~0x6, 0x6);
1455fb29ab96SDavid T.L. Wong 	else
1456a8bbf12aSHans Verkuil 		cx25840_and_or(client, 0x401, ~0x6, is_composite ? 0 : 0x02);
1457f234081bSSteven Toth 
145874900b47SSteven Toth 	if (is_cx2388x(state)) {
145974900b47SSteven Toth 		/* Enable or disable the DIF for tuner use */
146074900b47SSteven Toth 		if (is_dif) {
146174900b47SSteven Toth 			cx25840_and_or(client, 0x102, ~0x80, 0x80);
146274900b47SSteven Toth 
146374900b47SSteven Toth 			/* Set of defaults for NTSC and PAL */
146474900b47SSteven Toth 			cx25840_write4(client, 0x31c, 0xc2262600);
146574900b47SSteven Toth 			cx25840_write4(client, 0x320, 0xc2262600);
146674900b47SSteven Toth 
146774900b47SSteven Toth 			/* 18271 IF - Nobody else yet uses a different
146874900b47SSteven Toth 			 * tuner with the DIF, so these are reasonable
146974900b47SSteven Toth 			 * assumptions (HVR1250 and HVR1850 specific).
147074900b47SSteven Toth 			 */
147174900b47SSteven Toth 			cx25840_write4(client, 0x318, 0xda262600);
147274900b47SSteven Toth 			cx25840_write4(client, 0x33c, 0x2a24c800);
147374900b47SSteven Toth 			cx25840_write4(client, 0x104, 0x0704dd00);
147474900b47SSteven Toth 		} else {
147574900b47SSteven Toth 			cx25840_write4(client, 0x300, 0x015c28f5);
147674900b47SSteven Toth 
147774900b47SSteven Toth 			cx25840_and_or(client, 0x102, ~0x80, 0);
147874900b47SSteven Toth 			cx25840_write4(client, 0x340, 0xdf7df83);
147974900b47SSteven Toth 			cx25840_write4(client, 0x104, 0x0704dd80);
148074900b47SSteven Toth 			cx25840_write4(client, 0x314, 0x22400600);
148174900b47SSteven Toth 			cx25840_write4(client, 0x318, 0x40002600);
148274900b47SSteven Toth 			cx25840_write4(client, 0x324, 0x40002600);
148374900b47SSteven Toth 			cx25840_write4(client, 0x32c, 0x0250e620);
148474900b47SSteven Toth 			cx25840_write4(client, 0x39c, 0x01FF0B00);
148574900b47SSteven Toth 
148674900b47SSteven Toth 			cx25840_write4(client, 0x410, 0xffff0dbf);
148774900b47SSteven Toth 			cx25840_write4(client, 0x414, 0x00137d03);
1488e6d0db1dSDevin Heitmueller 
1489038fd414SBrad Love 			if (is_cx23888(state)) {
1490038fd414SBrad Love 				/* 888 MISC_TIM_CTRL */
1491038fd414SBrad Love 				cx25840_write4(client, 0x42c, 0x42600000);
1492038fd414SBrad Love 				/* 888 FIELD_COUNT */
1493038fd414SBrad Love 				cx25840_write4(client, 0x430, 0x0000039b);
1494038fd414SBrad Love 				/* 888 VSCALE_CTRL */
1495038fd414SBrad Love 				cx25840_write4(client, 0x438, 0x00000000);
1496038fd414SBrad Love 				/* 888 DFE_CTRL1 */
1497038fd414SBrad Love 				cx25840_write4(client, 0x440, 0xF8E3E824);
1498038fd414SBrad Love 				/* 888 DFE_CTRL2 */
1499038fd414SBrad Love 				cx25840_write4(client, 0x444, 0x401040dc);
1500038fd414SBrad Love 				/* 888 DFE_CTRL3 */
1501038fd414SBrad Love 				cx25840_write4(client, 0x448, 0xcd3f02a0);
1502038fd414SBrad Love 				/* 888 PLL_CTRL */
1503038fd414SBrad Love 				cx25840_write4(client, 0x44c, 0x161f1000);
1504038fd414SBrad Love 				/* 888 HTL_CTRL */
1505038fd414SBrad Love 				cx25840_write4(client, 0x450, 0x00000802);
1506038fd414SBrad Love 			}
150774900b47SSteven Toth 			cx25840_write4(client, 0x91c, 0x01000000);
150874900b47SSteven Toth 			cx25840_write4(client, 0x8e0, 0x03063870);
150974900b47SSteven Toth 			cx25840_write4(client, 0x8d4, 0x7FFF0024);
151074900b47SSteven Toth 			cx25840_write4(client, 0x8d0, 0x00063073);
151174900b47SSteven Toth 
151274900b47SSteven Toth 			cx25840_write4(client, 0x8c8, 0x00010000);
151374900b47SSteven Toth 			cx25840_write4(client, 0x8cc, 0x00080023);
151474900b47SSteven Toth 
151574900b47SSteven Toth 			/* DIF BYPASS */
151674900b47SSteven Toth 			cx25840_write4(client, 0x33c, 0x2a04c800);
151774900b47SSteven Toth 		}
151874900b47SSteven Toth 
151974900b47SSteven Toth 		/* Reset the DIF */
152074900b47SSteven Toth 		cx25840_write4(client, 0x398, 0);
152174900b47SSteven Toth 	}
152274900b47SSteven Toth 
15232a03f034SAndy Walls 	if (!is_cx2388x(state) && !is_cx231xx(state)) {
1524a8bbf12aSHans Verkuil 		/* Set CH_SEL_ADC2 to 1 if input comes from CH3 */
1525a8bbf12aSHans Verkuil 		cx25840_and_or(client, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0);
1526f234081bSSteven Toth 		/* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2&CH3 */
1527a8bbf12aSHans Verkuil 		if ((reg & 0xc0) != 0xc0 && (reg & 0x30) != 0x30)
1528a8bbf12aSHans Verkuil 			cx25840_and_or(client, 0x102, ~0x4, 4);
1529a8bbf12aSHans Verkuil 		else
1530a8bbf12aSHans Verkuil 			cx25840_and_or(client, 0x102, ~0x4, 0);
1531f234081bSSteven Toth 	} else {
1532fb29ab96SDavid T.L. Wong 		/* Set DUAL_MODE_ADC2 to 1 if component*/
1533fb29ab96SDavid T.L. Wong 		cx25840_and_or(client, 0x102, ~0x4, is_component ? 0x4 : 0x0);
1534fb29ab96SDavid T.L. Wong 		if (is_composite) {
1535f234081bSSteven Toth 			/* ADC2 input select channel 2 */
1536f234081bSSteven Toth 			cx25840_and_or(client, 0x102, ~0x2, 0);
1537fb29ab96SDavid T.L. Wong 		} else if (!is_component) {
1538fb29ab96SDavid T.L. Wong 			/* S-Video */
1539fb29ab96SDavid T.L. Wong 			if (chroma >= CX25840_SVIDEO_CHROMA7) {
1540f234081bSSteven Toth 				/* ADC2 input select channel 3 */
1541f234081bSSteven Toth 				cx25840_and_or(client, 0x102, ~0x2, 2);
1542fb29ab96SDavid T.L. Wong 			} else {
1543fb29ab96SDavid T.L. Wong 				/* ADC2 input select channel 2 */
1544fb29ab96SDavid T.L. Wong 				cx25840_and_or(client, 0x102, ~0x2, 0);
1545fb29ab96SDavid T.L. Wong 			}
1546fb29ab96SDavid T.L. Wong 		}
154774900b47SSteven Toth 
154874900b47SSteven Toth 		/* cx23885 / SVIDEO */
154974900b47SSteven Toth 		if (is_cx2388x(state) && is_svideo) {
155074900b47SSteven Toth #define AFE_CTRL  (0x104)
155174900b47SSteven Toth #define MODE_CTRL (0x400)
155274900b47SSteven Toth 			cx25840_and_or(client, 0x102, ~0x2, 0x2);
155374900b47SSteven Toth 
155474900b47SSteven Toth 			val = cx25840_read4(client, MODE_CTRL);
155574900b47SSteven Toth 			val &= 0xFFFFF9FF;
155674900b47SSteven Toth 
155774900b47SSteven Toth 			/* YC */
155874900b47SSteven Toth 			val |= 0x00000200;
155974900b47SSteven Toth 			val &= ~0x2000;
156074900b47SSteven Toth 			cx25840_write4(client, MODE_CTRL, val);
156174900b47SSteven Toth 
156274900b47SSteven Toth 			val = cx25840_read4(client, AFE_CTRL);
156374900b47SSteven Toth 
156474900b47SSteven Toth 			/* Chroma in select */
156574900b47SSteven Toth 			val |= 0x00001000;
156674900b47SSteven Toth 			val &= 0xfffffe7f;
156774900b47SSteven Toth 			/* Clear VGA_SEL_CH2 and VGA_SEL_CH3 (bits 7 and 8).
156874900b47SSteven Toth 			 * This sets them to use video rather than audio.
156974900b47SSteven Toth 			 * Only one of the two will be in use.
157074900b47SSteven Toth 			 */
157174900b47SSteven Toth 			cx25840_write4(client, AFE_CTRL, val);
157210a34367SMauro Carvalho Chehab 		} else {
157374900b47SSteven Toth 			cx25840_and_or(client, 0x102, ~0x2, 0);
1574f234081bSSteven Toth 		}
157510a34367SMauro Carvalho Chehab 	}
1576a8bbf12aSHans Verkuil 
1577a8bbf12aSHans Verkuil 	state->vid_input = vid_input;
1578a8bbf12aSHans Verkuil 	state->aud_input = aud_input;
1579a8bbf12aSHans Verkuil 	cx25840_audio_set_path(client);
1580bd985160SHans Verkuil 	input_change(client);
1581f234081bSSteven Toth 
15822a03f034SAndy Walls 	if (is_cx2388x(state)) {
1583f234081bSSteven Toth 		/* Audio channel 1 src : Parallel 1 */
1584f234081bSSteven Toth 		cx25840_write(client, 0x124, 0x03);
1585f234081bSSteven Toth 
1586f234081bSSteven Toth 		/* Select AFE clock pad output source */
1587f234081bSSteven Toth 		cx25840_write(client, 0x144, 0x05);
1588f234081bSSteven Toth 
1589f234081bSSteven Toth 		/* I2S_IN_CTL: I2S_IN_SONY_MODE, LEFT SAMPLE on WS=1 */
1590f234081bSSteven Toth 		cx25840_write(client, 0x914, 0xa0);
1591f234081bSSteven Toth 
1592f234081bSSteven Toth 		/* I2S_OUT_CTL:
1593f234081bSSteven Toth 		 * I2S_IN_SONY_MODE, LEFT SAMPLE on WS=1
1594f234081bSSteven Toth 		 * I2S_OUT_MASTER_MODE = Master
1595f234081bSSteven Toth 		 */
1596f234081bSSteven Toth 		cx25840_write(client, 0x918, 0xa0);
1597f234081bSSteven Toth 		cx25840_write(client, 0x919, 0x01);
15982a03f034SAndy Walls 	} else if (is_cx231xx(state)) {
1599149783b5SSri Deevi 		/* Audio channel 1 src : Parallel 1 */
1600149783b5SSri Deevi 		cx25840_write(client, 0x124, 0x03);
1601149783b5SSri Deevi 
1602149783b5SSri Deevi 		/* I2S_IN_CTL: I2S_IN_SONY_MODE, LEFT SAMPLE on WS=1 */
1603149783b5SSri Deevi 		cx25840_write(client, 0x914, 0xa0);
1604149783b5SSri Deevi 
1605149783b5SSri Deevi 		/* I2S_OUT_CTL:
1606149783b5SSri Deevi 		 * I2S_IN_SONY_MODE, LEFT SAMPLE on WS=1
1607149783b5SSri Deevi 		 * I2S_OUT_MASTER_MODE = Master
1608149783b5SSri Deevi 		 */
1609149783b5SSri Deevi 		cx25840_write(client, 0x918, 0xa0);
1610149783b5SSri Deevi 		cx25840_write(client, 0x919, 0x01);
1611f234081bSSteven Toth 	}
1612f234081bSSteven Toth 
161310a34367SMauro Carvalho Chehab 	if (is_cx2388x(state) &&
161410a34367SMauro Carvalho Chehab 	    ((aud_input == CX25840_AUDIO7) || (aud_input == CX25840_AUDIO6))) {
16152ccdd9a5SSteven Toth 		/* Configure audio from LR1 or LR2 input */
16162ccdd9a5SSteven Toth 		cx25840_write4(client, 0x910, 0);
16172ccdd9a5SSteven Toth 		cx25840_write4(client, 0x8d0, 0x63073);
161810a34367SMauro Carvalho Chehab 	} else if (is_cx2388x(state) && (aud_input == CX25840_AUDIO8)) {
16192ccdd9a5SSteven Toth 		/* Configure audio from tuner/sif input */
16202ccdd9a5SSteven Toth 		cx25840_write4(client, 0x910, 0x12b000c9);
16212ccdd9a5SSteven Toth 		cx25840_write4(client, 0x8d0, 0x1f063870);
16222ccdd9a5SSteven Toth 	}
16232ccdd9a5SSteven Toth 
1624d90133ecSDevin Heitmueller 	if (is_cx23888(state)) {
162510a34367SMauro Carvalho Chehab 		/*
162610a34367SMauro Carvalho Chehab 		 * HVR1850
162710a34367SMauro Carvalho Chehab 		 *
162810a34367SMauro Carvalho Chehab 		 * AUD_IO_CTRL - I2S Input, Parallel1
162910a34367SMauro Carvalho Chehab 		 *  - Channel 1 src - Parallel1 (Merlin out)
163010a34367SMauro Carvalho Chehab 		 *  - Channel 2 src - Parallel2 (Merlin out)
163110a34367SMauro Carvalho Chehab 		 *  - Channel 3 src - Parallel3 (Merlin AC97 out)
163210a34367SMauro Carvalho Chehab 		 *  - I2S source and dir - Merlin, output
163310a34367SMauro Carvalho Chehab 		 */
163474900b47SSteven Toth 		cx25840_write4(client, 0x124, 0x100);
163574900b47SSteven Toth 
163674900b47SSteven Toth 		if (!is_dif) {
163710a34367SMauro Carvalho Chehab 			/*
163810a34367SMauro Carvalho Chehab 			 * Stop microcontroller if we don't need it
163974900b47SSteven Toth 			 * to avoid audio popping on svideo/composite use.
164074900b47SSteven Toth 			 */
164174900b47SSteven Toth 			cx25840_and_or(client, 0x803, ~0x10, 0x00);
164274900b47SSteven Toth 		}
164374900b47SSteven Toth 	}
164474900b47SSteven Toth 
1645bd985160SHans Verkuil 	return 0;
1646bd985160SHans Verkuil }
1647bd985160SHans Verkuil 
1648bd985160SHans Verkuil /* ----------------------------------------------------------------------- */
1649bd985160SHans Verkuil 
set_v4lstd(struct i2c_client * client)1650081b496aSHans Verkuil static int set_v4lstd(struct i2c_client *client)
1651bd985160SHans Verkuil {
16529357b31cSHans Verkuil 	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
1653468a0a54SMauro Carvalho Chehab 	u8 fmt = 0;	/* zero is autodetect */
1654081b496aSHans Verkuil 	u8 pal_m = 0;
1655bd985160SHans Verkuil 
1656468a0a54SMauro Carvalho Chehab 	/* First tests should be against specific std */
1657081b496aSHans Verkuil 	if (state->std == V4L2_STD_NTSC_M_JP) {
1658468a0a54SMauro Carvalho Chehab 		fmt = 0x2;
1659081b496aSHans Verkuil 	} else if (state->std == V4L2_STD_NTSC_443) {
1660468a0a54SMauro Carvalho Chehab 		fmt = 0x3;
1661081b496aSHans Verkuil 	} else if (state->std == V4L2_STD_PAL_M) {
1662081b496aSHans Verkuil 		pal_m = 1;
1663468a0a54SMauro Carvalho Chehab 		fmt = 0x5;
1664081b496aSHans Verkuil 	} else if (state->std == V4L2_STD_PAL_N) {
1665468a0a54SMauro Carvalho Chehab 		fmt = 0x6;
1666081b496aSHans Verkuil 	} else if (state->std == V4L2_STD_PAL_Nc) {
1667468a0a54SMauro Carvalho Chehab 		fmt = 0x7;
1668081b496aSHans Verkuil 	} else if (state->std == V4L2_STD_PAL_60) {
1669468a0a54SMauro Carvalho Chehab 		fmt = 0x8;
1670468a0a54SMauro Carvalho Chehab 	} else {
1671468a0a54SMauro Carvalho Chehab 		/* Then, test against generic ones */
1672081b496aSHans Verkuil 		if (state->std & V4L2_STD_NTSC)
1673468a0a54SMauro Carvalho Chehab 			fmt = 0x1;
1674081b496aSHans Verkuil 		else if (state->std & V4L2_STD_PAL)
1675468a0a54SMauro Carvalho Chehab 			fmt = 0x4;
1676081b496aSHans Verkuil 		else if (state->std & V4L2_STD_SECAM)
1677468a0a54SMauro Carvalho Chehab 			fmt = 0xc;
1678468a0a54SMauro Carvalho Chehab 	}
1679bd985160SHans Verkuil 
168010a34367SMauro Carvalho Chehab 	v4l_dbg(1, cx25840_debug, client,
168110a34367SMauro Carvalho Chehab 		"changing video std to fmt %i\n", fmt);
1682839e4a4aSMauro Carvalho Chehab 
168310a34367SMauro Carvalho Chehab 	/*
168410a34367SMauro Carvalho Chehab 	 * Follow step 9 of section 3.16 in the cx25840 datasheet.
168510a34367SMauro Carvalho Chehab 	 * Without this PAL may display a vertical ghosting effect.
168610a34367SMauro Carvalho Chehab 	 * This happens for example with the Yuan MPC622.
168710a34367SMauro Carvalho Chehab 	 */
168873dcddc5SHans Verkuil 	if (fmt >= 4 && fmt < 8) {
168973dcddc5SHans Verkuil 		/* Set format to NTSC-M */
169073dcddc5SHans Verkuil 		cx25840_and_or(client, 0x400, ~0xf, 1);
169173dcddc5SHans Verkuil 		/* Turn off LCOMB */
169273dcddc5SHans Verkuil 		cx25840_and_or(client, 0x47b, ~6, 0);
169373dcddc5SHans Verkuil 	}
1694bd985160SHans Verkuil 	cx25840_and_or(client, 0x400, ~0xf, fmt);
1695081b496aSHans Verkuil 	cx25840_and_or(client, 0x403, ~0x3, pal_m);
1696ba50e7e1SDevin Heitmueller 	if (is_cx23888(state))
1697ba50e7e1SDevin Heitmueller 		cx23888_std_setup(client);
169874900b47SSteven Toth 	else
1699cb5aa1c6SHans Verkuil 		cx25840_std_setup(client);
17002a03f034SAndy Walls 	if (!is_cx2583x(state))
1701081b496aSHans Verkuil 		input_change(client);
1702bd985160SHans Verkuil 	return 0;
1703bd985160SHans Verkuil }
1704bd985160SHans Verkuil 
1705bd985160SHans Verkuil /* ----------------------------------------------------------------------- */
1706bd985160SHans Verkuil 
cx25840_s_ctrl(struct v4l2_ctrl * ctrl)1707e34e658bSHans Verkuil static int cx25840_s_ctrl(struct v4l2_ctrl *ctrl)
1708bd985160SHans Verkuil {
1709e34e658bSHans Verkuil 	struct v4l2_subdev *sd = to_sd(ctrl);
1710e6d0db1dSDevin Heitmueller 	struct cx25840_state *state = to_state(sd);
17119357b31cSHans Verkuil 	struct i2c_client *client = v4l2_get_subdevdata(sd);
1712bd985160SHans Verkuil 
1713bd985160SHans Verkuil 	switch (ctrl->id) {
1714bd985160SHans Verkuil 	case V4L2_CID_BRIGHTNESS:
1715e34e658bSHans Verkuil 		cx25840_write(client, 0x414, ctrl->val - 128);
1716bd985160SHans Verkuil 		break;
1717bd985160SHans Verkuil 
1718bd985160SHans Verkuil 	case V4L2_CID_CONTRAST:
1719e34e658bSHans Verkuil 		cx25840_write(client, 0x415, ctrl->val << 1);
1720bd985160SHans Verkuil 		break;
1721bd985160SHans Verkuil 
1722bd985160SHans Verkuil 	case V4L2_CID_SATURATION:
1723e6d0db1dSDevin Heitmueller 		if (is_cx23888(state)) {
1724e6d0db1dSDevin Heitmueller 			cx25840_write(client, 0x418, ctrl->val << 1);
1725e6d0db1dSDevin Heitmueller 			cx25840_write(client, 0x419, ctrl->val << 1);
1726e6d0db1dSDevin Heitmueller 		} else {
1727e34e658bSHans Verkuil 			cx25840_write(client, 0x420, ctrl->val << 1);
1728e34e658bSHans Verkuil 			cx25840_write(client, 0x421, ctrl->val << 1);
1729e6d0db1dSDevin Heitmueller 		}
1730bd985160SHans Verkuil 		break;
1731bd985160SHans Verkuil 
1732bd985160SHans Verkuil 	case V4L2_CID_HUE:
1733e6d0db1dSDevin Heitmueller 		if (is_cx23888(state))
1734e6d0db1dSDevin Heitmueller 			cx25840_write(client, 0x41a, ctrl->val);
1735e6d0db1dSDevin Heitmueller 		else
1736e34e658bSHans Verkuil 			cx25840_write(client, 0x422, ctrl->val);
1737bd985160SHans Verkuil 		break;
1738bd985160SHans Verkuil 
1739bd985160SHans Verkuil 	default:
1740bd985160SHans Verkuil 		return -EINVAL;
1741bd985160SHans Verkuil 	}
1742bd985160SHans Verkuil 
1743bd985160SHans Verkuil 	return 0;
1744bd985160SHans Verkuil }
1745bd985160SHans Verkuil 
1746bd985160SHans Verkuil /* ----------------------------------------------------------------------- */
1747bd985160SHans Verkuil 
cx25840_set_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_format * format)17486e80c473SHans Verkuil static int cx25840_set_fmt(struct v4l2_subdev *sd,
17490d346d2aSTomi Valkeinen 			   struct v4l2_subdev_state *sd_state,
17506e80c473SHans Verkuil 			   struct v4l2_subdev_format *format)
1751bd985160SHans Verkuil {
17526e80c473SHans Verkuil 	struct v4l2_mbus_framefmt *fmt = &format->format;
17539357b31cSHans Verkuil 	struct cx25840_state *state = to_state(sd);
17549357b31cSHans Verkuil 	struct i2c_client *client = v4l2_get_subdevdata(sd);
175510a34367SMauro Carvalho Chehab 	u32 hsc, vsc, v_src, h_src, v_add;
175665efeca0SMaciej S. Szmigiero 	int filter;
175710a34367SMauro Carvalho Chehab 	int is_50hz = !(state->std & V4L2_STD_525_60);
1758bd985160SHans Verkuil 
17596e80c473SHans Verkuil 	if (format->pad || fmt->code != MEDIA_BUS_FMT_FIXED)
176096fd004fSHans Verkuil 		return -EINVAL;
176196fd004fSHans Verkuil 
176296fd004fSHans Verkuil 	fmt->field = V4L2_FIELD_INTERLACED;
176396fd004fSHans Verkuil 	fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
1764bd985160SHans Verkuil 
1765b5c5c17bSDevin Heitmueller 	if (is_cx23888(state)) {
176610a34367SMauro Carvalho Chehab 		v_src = (cx25840_read(client, 0x42a) & 0x3f) << 4;
176710a34367SMauro Carvalho Chehab 		v_src |= (cx25840_read(client, 0x429) & 0xf0) >> 4;
1768b5c5c17bSDevin Heitmueller 	} else {
176910a34367SMauro Carvalho Chehab 		v_src = (cx25840_read(client, 0x476) & 0x3f) << 4;
177010a34367SMauro Carvalho Chehab 		v_src |= (cx25840_read(client, 0x475) & 0xf0) >> 4;
1771b5c5c17bSDevin Heitmueller 	}
1772bd985160SHans Verkuil 
1773b5c5c17bSDevin Heitmueller 	if (is_cx23888(state)) {
177410a34367SMauro Carvalho Chehab 		h_src = (cx25840_read(client, 0x426) & 0x3f) << 4;
177510a34367SMauro Carvalho Chehab 		h_src |= (cx25840_read(client, 0x425) & 0xf0) >> 4;
1776b5c5c17bSDevin Heitmueller 	} else {
177710a34367SMauro Carvalho Chehab 		h_src = (cx25840_read(client, 0x472) & 0x3f) << 4;
177810a34367SMauro Carvalho Chehab 		h_src |= (cx25840_read(client, 0x471) & 0xf0) >> 4;
1779b5c5c17bSDevin Heitmueller 	}
1780bd985160SHans Verkuil 
178165efeca0SMaciej S. Szmigiero 	if (!state->generic_mode) {
178210a34367SMauro Carvalho Chehab 		v_add = is_50hz ? 4 : 7;
1783bd985160SHans Verkuil 
1784499ebed3SHans Verkuil 		/*
178565efeca0SMaciej S. Szmigiero 		 * cx23888 in 525-line mode is programmed for 486 active lines
178665efeca0SMaciej S. Szmigiero 		 * while other chips use 487 active lines.
178765efeca0SMaciej S. Szmigiero 		 *
178865efeca0SMaciej S. Szmigiero 		 * See reg 0x428 bits [21:12] in cx23888_std_setup() vs
178965efeca0SMaciej S. Szmigiero 		 * vactive in cx25840_std_setup().
1790499ebed3SHans Verkuil 		 */
179110a34367SMauro Carvalho Chehab 		if (is_cx23888(state) && !is_50hz)
179210a34367SMauro Carvalho Chehab 			v_add--;
179310a34367SMauro Carvalho Chehab 	} else {
179410a34367SMauro Carvalho Chehab 		v_add = 0;
179510a34367SMauro Carvalho Chehab 	}
179665efeca0SMaciej S. Szmigiero 
179710a34367SMauro Carvalho Chehab 	if (h_src == 0 ||
179810a34367SMauro Carvalho Chehab 	    v_src <= v_add) {
179965efeca0SMaciej S. Szmigiero 		v4l_err(client,
180065efeca0SMaciej S. Szmigiero 			"chip reported picture size (%u x %u) is far too small\n",
180110a34367SMauro Carvalho Chehab 			(unsigned int)h_src, (unsigned int)v_src);
180265efeca0SMaciej S. Szmigiero 		/*
180365efeca0SMaciej S. Szmigiero 		 * that's the best we can do since the output picture
180465efeca0SMaciej S. Szmigiero 		 * size is completely unknown in this case
180565efeca0SMaciej S. Szmigiero 		 */
180665efeca0SMaciej S. Szmigiero 		return -EINVAL;
1807bd985160SHans Verkuil 	}
180865efeca0SMaciej S. Szmigiero 
180910a34367SMauro Carvalho Chehab 	fmt->width = clamp(fmt->width, (h_src + 15) / 16, h_src);
181065efeca0SMaciej S. Szmigiero 
181110a34367SMauro Carvalho Chehab 	if (v_add * 8 >= v_src)
181210a34367SMauro Carvalho Chehab 		fmt->height = clamp(fmt->height, (u32)1, v_src - v_add);
181365efeca0SMaciej S. Szmigiero 	else
181410a34367SMauro Carvalho Chehab 		fmt->height = clamp(fmt->height, (v_src - v_add * 8 + 7) / 8,
181510a34367SMauro Carvalho Chehab 				    v_src - v_add);
181665efeca0SMaciej S. Szmigiero 
18176e80c473SHans Verkuil 	if (format->which == V4L2_SUBDEV_FORMAT_TRY)
18186e80c473SHans Verkuil 		return 0;
1819bd985160SHans Verkuil 
182010a34367SMauro Carvalho Chehab 	hsc = (h_src * (1 << 20)) / fmt->width - (1 << 20);
182110a34367SMauro Carvalho Chehab 	vsc = (1 << 16) - (v_src * (1 << 9) / (fmt->height + v_add) - (1 << 9));
182210a34367SMauro Carvalho Chehab 	vsc &= 0x1fff;
1823bd985160SHans Verkuil 
182496fd004fSHans Verkuil 	if (fmt->width >= 385)
1825bd985160SHans Verkuil 		filter = 0;
182696fd004fSHans Verkuil 	else if (fmt->width > 192)
1827bd985160SHans Verkuil 		filter = 1;
182896fd004fSHans Verkuil 	else if (fmt->width > 96)
1829bd985160SHans Verkuil 		filter = 2;
1830bd985160SHans Verkuil 	else
1831bd985160SHans Verkuil 		filter = 3;
1832bd985160SHans Verkuil 
183365efeca0SMaciej S. Szmigiero 	v4l_dbg(1, cx25840_debug, client,
183465efeca0SMaciej S. Szmigiero 		"decoder set size %u x %u with scale %x x %x\n",
183565efeca0SMaciej S. Szmigiero 		(unsigned int)fmt->width, (unsigned int)fmt->height,
183610a34367SMauro Carvalho Chehab 		(unsigned int)hsc, (unsigned int)vsc);
1837bd985160SHans Verkuil 
183810a34367SMauro Carvalho Chehab 	/* HSCALE=hsc */
1839ee61cd9fSHans Verkuil 	if (is_cx23888(state)) {
184010a34367SMauro Carvalho Chehab 		cx25840_write4(client, 0x434, hsc | (1 << 24));
184110a34367SMauro Carvalho Chehab 		/* VSCALE=vsc VS_INTRLACE=1 VFILT=filter */
184210a34367SMauro Carvalho Chehab 		cx25840_write4(client, 0x438, vsc | (1 << 19) | (filter << 16));
1843ee61cd9fSHans Verkuil 	} else {
184410a34367SMauro Carvalho Chehab 		cx25840_write(client, 0x418, hsc & 0xff);
184510a34367SMauro Carvalho Chehab 		cx25840_write(client, 0x419, (hsc >> 8) & 0xff);
184610a34367SMauro Carvalho Chehab 		cx25840_write(client, 0x41a, hsc >> 16);
184710a34367SMauro Carvalho Chehab 		/* VSCALE=vsc */
184810a34367SMauro Carvalho Chehab 		cx25840_write(client, 0x41c, vsc & 0xff);
184910a34367SMauro Carvalho Chehab 		cx25840_write(client, 0x41d, vsc >> 8);
1850bd985160SHans Verkuil 		/* VS_INTRLACE=1 VFILT=filter */
1851bd985160SHans Verkuil 		cx25840_write(client, 0x41e, 0x8 | filter);
1852ee61cd9fSHans Verkuil 	}
185396fd004fSHans Verkuil 	return 0;
185496fd004fSHans Verkuil }
185596fd004fSHans Verkuil 
1856bd985160SHans Verkuil /* ----------------------------------------------------------------------- */
1857bd985160SHans Verkuil 
log_video_status(struct i2c_client * client)18581a39275aSHans Verkuil static void log_video_status(struct i2c_client *client)
18591a39275aSHans Verkuil {
18601a39275aSHans Verkuil 	static const char *const fmt_strs[] = {
18611a39275aSHans Verkuil 		"0x0",
18621a39275aSHans Verkuil 		"NTSC-M", "NTSC-J", "NTSC-4.43",
18631a39275aSHans Verkuil 		"PAL-BDGHI", "PAL-M", "PAL-N", "PAL-Nc", "PAL-60",
18641a39275aSHans Verkuil 		"0x9", "0xA", "0xB",
18651a39275aSHans Verkuil 		"SECAM",
18661a39275aSHans Verkuil 		"0xD", "0xE", "0xF"
18671a39275aSHans Verkuil 	};
18681a39275aSHans Verkuil 
18699357b31cSHans Verkuil 	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
18701a39275aSHans Verkuil 	u8 vidfmt_sel = cx25840_read(client, 0x400) & 0xf;
18711a39275aSHans Verkuil 	u8 gen_stat1 = cx25840_read(client, 0x40d);
18721a39275aSHans Verkuil 	u8 gen_stat2 = cx25840_read(client, 0x40e);
18731a39275aSHans Verkuil 	int vid_input = state->vid_input;
18741a39275aSHans Verkuil 
18751a39275aSHans Verkuil 	v4l_info(client, "Video signal:              %spresent\n",
18761a39275aSHans Verkuil 		 (gen_stat2 & 0x20) ? "" : "not ");
18771a39275aSHans Verkuil 	v4l_info(client, "Detected format:           %s\n",
18781a39275aSHans Verkuil 		 fmt_strs[gen_stat1 & 0xf]);
18791a39275aSHans Verkuil 
18801a39275aSHans Verkuil 	v4l_info(client, "Specified standard:        %s\n",
18811a39275aSHans Verkuil 		 vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection");
18821a39275aSHans Verkuil 
18831a39275aSHans Verkuil 	if (vid_input >= CX25840_COMPOSITE1 &&
18841a39275aSHans Verkuil 	    vid_input <= CX25840_COMPOSITE8) {
18851a39275aSHans Verkuil 		v4l_info(client, "Specified video input:     Composite %d\n",
18861a39275aSHans Verkuil 			 vid_input - CX25840_COMPOSITE1 + 1);
18871a39275aSHans Verkuil 	} else {
188810a34367SMauro Carvalho Chehab 		v4l_info(client,
188910a34367SMauro Carvalho Chehab 			 "Specified video input:     S-Video (Luma In%d, Chroma In%d)\n",
18901a39275aSHans Verkuil 			 (vid_input & 0xf0) >> 4, (vid_input & 0xf00) >> 8);
18911a39275aSHans Verkuil 	}
18921a39275aSHans Verkuil 
189310a34367SMauro Carvalho Chehab 	v4l_info(client, "Specified audioclock freq: %d Hz\n",
189410a34367SMauro Carvalho Chehab 		 state->audclk_freq);
18951a39275aSHans Verkuil }
18961a39275aSHans Verkuil 
18971a39275aSHans Verkuil /* ----------------------------------------------------------------------- */
18981a39275aSHans Verkuil 
log_audio_status(struct i2c_client * client)18991a39275aSHans Verkuil static void log_audio_status(struct i2c_client *client)
19001a39275aSHans Verkuil {
19019357b31cSHans Verkuil 	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
19021a39275aSHans Verkuil 	u8 download_ctl = cx25840_read(client, 0x803);
19031a39275aSHans Verkuil 	u8 mod_det_stat0 = cx25840_read(client, 0x804);
19041a39275aSHans Verkuil 	u8 mod_det_stat1 = cx25840_read(client, 0x805);
19051a39275aSHans Verkuil 	u8 audio_config = cx25840_read(client, 0x808);
19061a39275aSHans Verkuil 	u8 pref_mode = cx25840_read(client, 0x809);
19071a39275aSHans Verkuil 	u8 afc0 = cx25840_read(client, 0x80b);
19081a39275aSHans Verkuil 	u8 mute_ctl = cx25840_read(client, 0x8d3);
19091a39275aSHans Verkuil 	int aud_input = state->aud_input;
19101a39275aSHans Verkuil 	char *p;
19111a39275aSHans Verkuil 
19121a39275aSHans Verkuil 	switch (mod_det_stat0) {
191310a34367SMauro Carvalho Chehab 	case 0x00:
191410a34367SMauro Carvalho Chehab 		p = "mono";
191510a34367SMauro Carvalho Chehab 		break;
191610a34367SMauro Carvalho Chehab 	case 0x01:
191710a34367SMauro Carvalho Chehab 		p = "stereo";
191810a34367SMauro Carvalho Chehab 		break;
191910a34367SMauro Carvalho Chehab 	case 0x02:
192010a34367SMauro Carvalho Chehab 		p = "dual";
192110a34367SMauro Carvalho Chehab 		break;
192210a34367SMauro Carvalho Chehab 	case 0x04:
192310a34367SMauro Carvalho Chehab 		p = "tri";
192410a34367SMauro Carvalho Chehab 		break;
192510a34367SMauro Carvalho Chehab 	case 0x10:
192610a34367SMauro Carvalho Chehab 		p = "mono with SAP";
192710a34367SMauro Carvalho Chehab 		break;
192810a34367SMauro Carvalho Chehab 	case 0x11:
192910a34367SMauro Carvalho Chehab 		p = "stereo with SAP";
193010a34367SMauro Carvalho Chehab 		break;
193110a34367SMauro Carvalho Chehab 	case 0x12:
193210a34367SMauro Carvalho Chehab 		p = "dual with SAP";
193310a34367SMauro Carvalho Chehab 		break;
193410a34367SMauro Carvalho Chehab 	case 0x14:
193510a34367SMauro Carvalho Chehab 		p = "tri with SAP";
193610a34367SMauro Carvalho Chehab 		break;
193710a34367SMauro Carvalho Chehab 	case 0xfe:
193810a34367SMauro Carvalho Chehab 		p = "forced mode";
193910a34367SMauro Carvalho Chehab 		break;
194010a34367SMauro Carvalho Chehab 	default:
194110a34367SMauro Carvalho Chehab 		p = "not defined";
19421a39275aSHans Verkuil 	}
19431a39275aSHans Verkuil 	v4l_info(client, "Detected audio mode:       %s\n", p);
19441a39275aSHans Verkuil 
19451a39275aSHans Verkuil 	switch (mod_det_stat1) {
194610a34367SMauro Carvalho Chehab 	case 0x00:
194710a34367SMauro Carvalho Chehab 		p = "not defined";
194810a34367SMauro Carvalho Chehab 		break;
194910a34367SMauro Carvalho Chehab 	case 0x01:
195010a34367SMauro Carvalho Chehab 		p = "EIAJ";
195110a34367SMauro Carvalho Chehab 		break;
195210a34367SMauro Carvalho Chehab 	case 0x02:
195310a34367SMauro Carvalho Chehab 		p = "A2-M";
195410a34367SMauro Carvalho Chehab 		break;
195510a34367SMauro Carvalho Chehab 	case 0x03:
195610a34367SMauro Carvalho Chehab 		p = "A2-BG";
195710a34367SMauro Carvalho Chehab 		break;
195810a34367SMauro Carvalho Chehab 	case 0x04:
195910a34367SMauro Carvalho Chehab 		p = "A2-DK1";
196010a34367SMauro Carvalho Chehab 		break;
196110a34367SMauro Carvalho Chehab 	case 0x05:
196210a34367SMauro Carvalho Chehab 		p = "A2-DK2";
196310a34367SMauro Carvalho Chehab 		break;
196410a34367SMauro Carvalho Chehab 	case 0x06:
196510a34367SMauro Carvalho Chehab 		p = "A2-DK3";
196610a34367SMauro Carvalho Chehab 		break;
196710a34367SMauro Carvalho Chehab 	case 0x07:
196810a34367SMauro Carvalho Chehab 		p = "A1 (6.0 MHz FM Mono)";
196910a34367SMauro Carvalho Chehab 		break;
197010a34367SMauro Carvalho Chehab 	case 0x08:
197110a34367SMauro Carvalho Chehab 		p = "AM-L";
197210a34367SMauro Carvalho Chehab 		break;
197310a34367SMauro Carvalho Chehab 	case 0x09:
197410a34367SMauro Carvalho Chehab 		p = "NICAM-BG";
197510a34367SMauro Carvalho Chehab 		break;
197610a34367SMauro Carvalho Chehab 	case 0x0a:
197710a34367SMauro Carvalho Chehab 		p = "NICAM-DK";
197810a34367SMauro Carvalho Chehab 		break;
197910a34367SMauro Carvalho Chehab 	case 0x0b:
198010a34367SMauro Carvalho Chehab 		p = "NICAM-I";
198110a34367SMauro Carvalho Chehab 		break;
198210a34367SMauro Carvalho Chehab 	case 0x0c:
198310a34367SMauro Carvalho Chehab 		p = "NICAM-L";
198410a34367SMauro Carvalho Chehab 		break;
198510a34367SMauro Carvalho Chehab 	case 0x0d:
198610a34367SMauro Carvalho Chehab 		p = "BTSC/EIAJ/A2-M Mono (4.5 MHz FMMono)";
198710a34367SMauro Carvalho Chehab 		break;
198810a34367SMauro Carvalho Chehab 	case 0x0e:
198910a34367SMauro Carvalho Chehab 		p = "IF FM Radio";
199010a34367SMauro Carvalho Chehab 		break;
199110a34367SMauro Carvalho Chehab 	case 0x0f:
199210a34367SMauro Carvalho Chehab 		p = "BTSC";
199310a34367SMauro Carvalho Chehab 		break;
199410a34367SMauro Carvalho Chehab 	case 0x10:
199510a34367SMauro Carvalho Chehab 		p = "high-deviation FM";
199610a34367SMauro Carvalho Chehab 		break;
199710a34367SMauro Carvalho Chehab 	case 0x11:
199810a34367SMauro Carvalho Chehab 		p = "very high-deviation FM";
199910a34367SMauro Carvalho Chehab 		break;
200010a34367SMauro Carvalho Chehab 	case 0xfd:
200110a34367SMauro Carvalho Chehab 		p = "unknown audio standard";
200210a34367SMauro Carvalho Chehab 		break;
200310a34367SMauro Carvalho Chehab 	case 0xfe:
200410a34367SMauro Carvalho Chehab 		p = "forced audio standard";
200510a34367SMauro Carvalho Chehab 		break;
200610a34367SMauro Carvalho Chehab 	case 0xff:
200710a34367SMauro Carvalho Chehab 		p = "no detected audio standard";
200810a34367SMauro Carvalho Chehab 		break;
200910a34367SMauro Carvalho Chehab 	default:
201010a34367SMauro Carvalho Chehab 		p = "not defined";
20111a39275aSHans Verkuil 	}
20121a39275aSHans Verkuil 	v4l_info(client, "Detected audio standard:   %s\n", p);
20131a39275aSHans Verkuil 	v4l_info(client, "Audio microcontroller:     %s\n",
20141a39275aSHans Verkuil 		 (download_ctl & 0x10) ?
20151a39275aSHans Verkuil 		 ((mute_ctl & 0x2) ? "detecting" : "running") : "stopped");
20161a39275aSHans Verkuil 
20171a39275aSHans Verkuil 	switch (audio_config >> 4) {
201810a34367SMauro Carvalho Chehab 	case 0x00:
201910a34367SMauro Carvalho Chehab 		p = "undefined";
202010a34367SMauro Carvalho Chehab 		break;
202110a34367SMauro Carvalho Chehab 	case 0x01:
202210a34367SMauro Carvalho Chehab 		p = "BTSC";
202310a34367SMauro Carvalho Chehab 		break;
202410a34367SMauro Carvalho Chehab 	case 0x02:
202510a34367SMauro Carvalho Chehab 		p = "EIAJ";
202610a34367SMauro Carvalho Chehab 		break;
202710a34367SMauro Carvalho Chehab 	case 0x03:
202810a34367SMauro Carvalho Chehab 		p = "A2-M";
202910a34367SMauro Carvalho Chehab 		break;
203010a34367SMauro Carvalho Chehab 	case 0x04:
203110a34367SMauro Carvalho Chehab 		p = "A2-BG";
203210a34367SMauro Carvalho Chehab 		break;
203310a34367SMauro Carvalho Chehab 	case 0x05:
203410a34367SMauro Carvalho Chehab 		p = "A2-DK1";
203510a34367SMauro Carvalho Chehab 		break;
203610a34367SMauro Carvalho Chehab 	case 0x06:
203710a34367SMauro Carvalho Chehab 		p = "A2-DK2";
203810a34367SMauro Carvalho Chehab 		break;
203910a34367SMauro Carvalho Chehab 	case 0x07:
204010a34367SMauro Carvalho Chehab 		p = "A2-DK3";
204110a34367SMauro Carvalho Chehab 		break;
204210a34367SMauro Carvalho Chehab 	case 0x08:
204310a34367SMauro Carvalho Chehab 		p = "A1 (6.0 MHz FM Mono)";
204410a34367SMauro Carvalho Chehab 		break;
204510a34367SMauro Carvalho Chehab 	case 0x09:
204610a34367SMauro Carvalho Chehab 		p = "AM-L";
204710a34367SMauro Carvalho Chehab 		break;
204810a34367SMauro Carvalho Chehab 	case 0x0a:
204910a34367SMauro Carvalho Chehab 		p = "NICAM-BG";
205010a34367SMauro Carvalho Chehab 		break;
205110a34367SMauro Carvalho Chehab 	case 0x0b:
205210a34367SMauro Carvalho Chehab 		p = "NICAM-DK";
205310a34367SMauro Carvalho Chehab 		break;
205410a34367SMauro Carvalho Chehab 	case 0x0c:
205510a34367SMauro Carvalho Chehab 		p = "NICAM-I";
205610a34367SMauro Carvalho Chehab 		break;
205710a34367SMauro Carvalho Chehab 	case 0x0d:
205810a34367SMauro Carvalho Chehab 		p = "NICAM-L";
205910a34367SMauro Carvalho Chehab 		break;
206010a34367SMauro Carvalho Chehab 	case 0x0e:
206110a34367SMauro Carvalho Chehab 		p = "FM radio";
206210a34367SMauro Carvalho Chehab 		break;
206310a34367SMauro Carvalho Chehab 	case 0x0f:
206410a34367SMauro Carvalho Chehab 		p = "automatic detection";
206510a34367SMauro Carvalho Chehab 		break;
206610a34367SMauro Carvalho Chehab 	default:
206710a34367SMauro Carvalho Chehab 		p = "undefined";
20681a39275aSHans Verkuil 	}
20691a39275aSHans Verkuil 	v4l_info(client, "Configured audio standard: %s\n", p);
20701a39275aSHans Verkuil 
20711a39275aSHans Verkuil 	if ((audio_config >> 4) < 0xF) {
20721a39275aSHans Verkuil 		switch (audio_config & 0xF) {
207310a34367SMauro Carvalho Chehab 		case 0x00:
207410a34367SMauro Carvalho Chehab 			p = "MONO1 (LANGUAGE A/Mono L+R channel for BTSC, EIAJ, A2)";
207510a34367SMauro Carvalho Chehab 			break;
207610a34367SMauro Carvalho Chehab 		case 0x01:
207710a34367SMauro Carvalho Chehab 			p = "MONO2 (LANGUAGE B)";
207810a34367SMauro Carvalho Chehab 			break;
207910a34367SMauro Carvalho Chehab 		case 0x02:
208010a34367SMauro Carvalho Chehab 			p = "MONO3 (STEREO forced MONO)";
208110a34367SMauro Carvalho Chehab 			break;
208210a34367SMauro Carvalho Chehab 		case 0x03:
208310a34367SMauro Carvalho Chehab 			p = "MONO4 (NICAM ANALOG-Language C/Analog Fallback)";
208410a34367SMauro Carvalho Chehab 			break;
208510a34367SMauro Carvalho Chehab 		case 0x04:
208610a34367SMauro Carvalho Chehab 			p = "STEREO";
208710a34367SMauro Carvalho Chehab 			break;
208810a34367SMauro Carvalho Chehab 		case 0x05:
208910a34367SMauro Carvalho Chehab 			p = "DUAL1 (AB)";
209010a34367SMauro Carvalho Chehab 			break;
209110a34367SMauro Carvalho Chehab 		case 0x06:
209210a34367SMauro Carvalho Chehab 			p = "DUAL2 (AC) (FM)";
209310a34367SMauro Carvalho Chehab 			break;
209410a34367SMauro Carvalho Chehab 		case 0x07:
209510a34367SMauro Carvalho Chehab 			p = "DUAL3 (BC) (FM)";
209610a34367SMauro Carvalho Chehab 			break;
209710a34367SMauro Carvalho Chehab 		case 0x08:
209810a34367SMauro Carvalho Chehab 			p = "DUAL4 (AC) (AM)";
209910a34367SMauro Carvalho Chehab 			break;
210010a34367SMauro Carvalho Chehab 		case 0x09:
210110a34367SMauro Carvalho Chehab 			p = "DUAL5 (BC) (AM)";
210210a34367SMauro Carvalho Chehab 			break;
210310a34367SMauro Carvalho Chehab 		case 0x0a:
210410a34367SMauro Carvalho Chehab 			p = "SAP";
210510a34367SMauro Carvalho Chehab 			break;
210610a34367SMauro Carvalho Chehab 		default:
210710a34367SMauro Carvalho Chehab 			p = "undefined";
21081a39275aSHans Verkuil 		}
21091a39275aSHans Verkuil 		v4l_info(client, "Configured audio mode:     %s\n", p);
21101a39275aSHans Verkuil 	} else {
21111a39275aSHans Verkuil 		switch (audio_config & 0xF) {
211210a34367SMauro Carvalho Chehab 		case 0x00:
211310a34367SMauro Carvalho Chehab 			p = "BG";
211410a34367SMauro Carvalho Chehab 			break;
211510a34367SMauro Carvalho Chehab 		case 0x01:
211610a34367SMauro Carvalho Chehab 			p = "DK1";
211710a34367SMauro Carvalho Chehab 			break;
211810a34367SMauro Carvalho Chehab 		case 0x02:
211910a34367SMauro Carvalho Chehab 			p = "DK2";
212010a34367SMauro Carvalho Chehab 			break;
212110a34367SMauro Carvalho Chehab 		case 0x03:
212210a34367SMauro Carvalho Chehab 			p = "DK3";
212310a34367SMauro Carvalho Chehab 			break;
212410a34367SMauro Carvalho Chehab 		case 0x04:
212510a34367SMauro Carvalho Chehab 			p = "I";
212610a34367SMauro Carvalho Chehab 			break;
212710a34367SMauro Carvalho Chehab 		case 0x05:
212810a34367SMauro Carvalho Chehab 			p = "L";
212910a34367SMauro Carvalho Chehab 			break;
213010a34367SMauro Carvalho Chehab 		case 0x06:
213110a34367SMauro Carvalho Chehab 			p = "BTSC";
213210a34367SMauro Carvalho Chehab 			break;
213310a34367SMauro Carvalho Chehab 		case 0x07:
213410a34367SMauro Carvalho Chehab 			p = "EIAJ";
213510a34367SMauro Carvalho Chehab 			break;
213610a34367SMauro Carvalho Chehab 		case 0x08:
213710a34367SMauro Carvalho Chehab 			p = "A2-M";
213810a34367SMauro Carvalho Chehab 			break;
213910a34367SMauro Carvalho Chehab 		case 0x09:
214010a34367SMauro Carvalho Chehab 			p = "FM Radio";
214110a34367SMauro Carvalho Chehab 			break;
214210a34367SMauro Carvalho Chehab 		case 0x0f:
214310a34367SMauro Carvalho Chehab 			p = "automatic standard and mode detection";
214410a34367SMauro Carvalho Chehab 			break;
214510a34367SMauro Carvalho Chehab 		default:
214610a34367SMauro Carvalho Chehab 			p = "undefined";
21471a39275aSHans Verkuil 		}
21481a39275aSHans Verkuil 		v4l_info(client, "Configured audio system:   %s\n", p);
21491a39275aSHans Verkuil 	}
21501a39275aSHans Verkuil 
21511a39275aSHans Verkuil 	if (aud_input) {
215210a34367SMauro Carvalho Chehab 		v4l_info(client, "Specified audio input:     Tuner (In%d)\n",
215310a34367SMauro Carvalho Chehab 			 aud_input);
21541a39275aSHans Verkuil 	} else {
21551a39275aSHans Verkuil 		v4l_info(client, "Specified audio input:     External\n");
21561a39275aSHans Verkuil 	}
21571a39275aSHans Verkuil 
21581a39275aSHans Verkuil 	switch (pref_mode & 0xf) {
215910a34367SMauro Carvalho Chehab 	case 0:
216010a34367SMauro Carvalho Chehab 		p = "mono/language A";
216110a34367SMauro Carvalho Chehab 		break;
216210a34367SMauro Carvalho Chehab 	case 1:
216310a34367SMauro Carvalho Chehab 		p = "language B";
216410a34367SMauro Carvalho Chehab 		break;
216510a34367SMauro Carvalho Chehab 	case 2:
216610a34367SMauro Carvalho Chehab 		p = "language C";
216710a34367SMauro Carvalho Chehab 		break;
216810a34367SMauro Carvalho Chehab 	case 3:
216910a34367SMauro Carvalho Chehab 		p = "analog fallback";
217010a34367SMauro Carvalho Chehab 		break;
217110a34367SMauro Carvalho Chehab 	case 4:
217210a34367SMauro Carvalho Chehab 		p = "stereo";
217310a34367SMauro Carvalho Chehab 		break;
217410a34367SMauro Carvalho Chehab 	case 5:
217510a34367SMauro Carvalho Chehab 		p = "language AC";
217610a34367SMauro Carvalho Chehab 		break;
217710a34367SMauro Carvalho Chehab 	case 6:
217810a34367SMauro Carvalho Chehab 		p = "language BC";
217910a34367SMauro Carvalho Chehab 		break;
218010a34367SMauro Carvalho Chehab 	case 7:
218110a34367SMauro Carvalho Chehab 		p = "language AB";
218210a34367SMauro Carvalho Chehab 		break;
218310a34367SMauro Carvalho Chehab 	default:
218410a34367SMauro Carvalho Chehab 		p = "undefined";
21851a39275aSHans Verkuil 	}
21861a39275aSHans Verkuil 	v4l_info(client, "Preferred audio mode:      %s\n", p);
21871a39275aSHans Verkuil 
21881a39275aSHans Verkuil 	if ((audio_config & 0xf) == 0xf) {
21891a39275aSHans Verkuil 		switch ((afc0 >> 3) & 0x3) {
219010a34367SMauro Carvalho Chehab 		case 0:
219110a34367SMauro Carvalho Chehab 			p = "system DK";
219210a34367SMauro Carvalho Chehab 			break;
219310a34367SMauro Carvalho Chehab 		case 1:
219410a34367SMauro Carvalho Chehab 			p = "system L";
219510a34367SMauro Carvalho Chehab 			break;
219610a34367SMauro Carvalho Chehab 		case 2:
219710a34367SMauro Carvalho Chehab 			p = "autodetect";
219810a34367SMauro Carvalho Chehab 			break;
219910a34367SMauro Carvalho Chehab 		default:
220010a34367SMauro Carvalho Chehab 			p = "undefined";
22011a39275aSHans Verkuil 		}
22021a39275aSHans Verkuil 		v4l_info(client, "Selected 65 MHz format:    %s\n", p);
22031a39275aSHans Verkuil 
22041a39275aSHans Verkuil 		switch (afc0 & 0x7) {
220510a34367SMauro Carvalho Chehab 		case 0:
220610a34367SMauro Carvalho Chehab 			p = "chroma";
220710a34367SMauro Carvalho Chehab 			break;
220810a34367SMauro Carvalho Chehab 		case 1:
220910a34367SMauro Carvalho Chehab 			p = "BTSC";
221010a34367SMauro Carvalho Chehab 			break;
221110a34367SMauro Carvalho Chehab 		case 2:
221210a34367SMauro Carvalho Chehab 			p = "EIAJ";
221310a34367SMauro Carvalho Chehab 			break;
221410a34367SMauro Carvalho Chehab 		case 3:
221510a34367SMauro Carvalho Chehab 			p = "A2-M";
221610a34367SMauro Carvalho Chehab 			break;
221710a34367SMauro Carvalho Chehab 		case 4:
221810a34367SMauro Carvalho Chehab 			p = "autodetect";
221910a34367SMauro Carvalho Chehab 			break;
222010a34367SMauro Carvalho Chehab 		default:
222110a34367SMauro Carvalho Chehab 			p = "undefined";
22221a39275aSHans Verkuil 		}
22231a39275aSHans Verkuil 		v4l_info(client, "Selected 45 MHz format:    %s\n", p);
22241a39275aSHans Verkuil 	}
22251a39275aSHans Verkuil }
22261a39275aSHans Verkuil 
2227e81a9076SMaciej S. Szmigiero #define CX25840_VCONFIG_OPTION(state, cfg_in, opt_msk)			\
2228e81a9076SMaciej S. Szmigiero 	do {								\
2229e81a9076SMaciej S. Szmigiero 		if ((cfg_in) & (opt_msk)) {				\
2230e81a9076SMaciej S. Szmigiero 			(state)->vid_config &= ~(opt_msk);		\
2231e81a9076SMaciej S. Szmigiero 			(state)->vid_config |= (cfg_in) & (opt_msk);	\
2232e81a9076SMaciej S. Szmigiero 		}							\
2233e81a9076SMaciej S. Szmigiero 	} while (0)
2234e81a9076SMaciej S. Szmigiero 
2235e81a9076SMaciej S. Szmigiero /* apply incoming options to the current vconfig */
cx25840_vconfig_add(struct cx25840_state * state,u32 cfg_in)2236e81a9076SMaciej S. Szmigiero static void cx25840_vconfig_add(struct cx25840_state *state, u32 cfg_in)
2237e81a9076SMaciej S. Szmigiero {
2238e81a9076SMaciej S. Szmigiero 	CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_FMT_MASK);
2239e81a9076SMaciej S. Szmigiero 	CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_RES_MASK);
2240e81a9076SMaciej S. Szmigiero 	CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_VBIRAW_MASK);
2241e81a9076SMaciej S. Szmigiero 	CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_ANCDATA_MASK);
2242e81a9076SMaciej S. Szmigiero 	CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_TASKBIT_MASK);
2243e81a9076SMaciej S. Szmigiero 	CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_ACTIVE_MASK);
2244e81a9076SMaciej S. Szmigiero 	CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_VALID_MASK);
2245e81a9076SMaciej S. Szmigiero 	CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_HRESETW_MASK);
2246e81a9076SMaciej S. Szmigiero 	CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_CLKGATE_MASK);
2247e81a9076SMaciej S. Szmigiero 	CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_DCMODE_MASK);
2248e81a9076SMaciej S. Szmigiero 	CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_IDID0S_MASK);
2249e81a9076SMaciej S. Szmigiero 	CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_VIPCLAMP_MASK);
2250e81a9076SMaciej S. Szmigiero }
2251e81a9076SMaciej S. Szmigiero 
22521a39275aSHans Verkuil /* ----------------------------------------------------------------------- */
22531a39275aSHans Verkuil 
2254e81a9076SMaciej S. Szmigiero /*
2255e81a9076SMaciej S. Szmigiero  * Initializes the device in the generic mode.
2256e81a9076SMaciej S. Szmigiero  * For cx2584x chips also adds additional video output settings provided
2257e81a9076SMaciej S. Szmigiero  * in @val parameter (CX25840_VCONFIG_*).
2258e81a9076SMaciej S. Szmigiero  *
2259e81a9076SMaciej S. Szmigiero  * The generic mode disables some of the ivtv-related hacks in this driver.
2260e81a9076SMaciej S. Szmigiero  * For cx2584x chips it also enables setting video output configuration while
2261e81a9076SMaciej S. Szmigiero  * setting it according to datasheet defaults by default.
2262e81a9076SMaciej S. Szmigiero  */
cx25840_init(struct v4l2_subdev * sd,u32 val)2263e81a9076SMaciej S. Szmigiero static int cx25840_init(struct v4l2_subdev *sd, u32 val)
2264e81a9076SMaciej S. Szmigiero {
2265e81a9076SMaciej S. Szmigiero 	struct cx25840_state *state = to_state(sd);
2266e81a9076SMaciej S. Szmigiero 
2267e81a9076SMaciej S. Szmigiero 	state->generic_mode = true;
2268e81a9076SMaciej S. Szmigiero 
2269e81a9076SMaciej S. Szmigiero 	if (is_cx2584x(state)) {
2270e81a9076SMaciej S. Szmigiero 		/* set datasheet video output defaults */
2271e81a9076SMaciej S. Szmigiero 		state->vid_config = CX25840_VCONFIG_FMT_BT656 |
2272e81a9076SMaciej S. Szmigiero 				    CX25840_VCONFIG_RES_8BIT |
2273e81a9076SMaciej S. Szmigiero 				    CX25840_VCONFIG_VBIRAW_DISABLED |
2274e81a9076SMaciej S. Szmigiero 				    CX25840_VCONFIG_ANCDATA_ENABLED |
2275e81a9076SMaciej S. Szmigiero 				    CX25840_VCONFIG_TASKBIT_ONE |
2276e81a9076SMaciej S. Szmigiero 				    CX25840_VCONFIG_ACTIVE_HORIZONTAL |
2277e81a9076SMaciej S. Szmigiero 				    CX25840_VCONFIG_VALID_NORMAL |
2278e81a9076SMaciej S. Szmigiero 				    CX25840_VCONFIG_HRESETW_NORMAL |
2279e81a9076SMaciej S. Szmigiero 				    CX25840_VCONFIG_CLKGATE_NONE |
2280e81a9076SMaciej S. Szmigiero 				    CX25840_VCONFIG_DCMODE_DWORDS |
2281e81a9076SMaciej S. Szmigiero 				    CX25840_VCONFIG_IDID0S_NORMAL |
2282e81a9076SMaciej S. Szmigiero 				    CX25840_VCONFIG_VIPCLAMP_DISABLED;
2283e81a9076SMaciej S. Szmigiero 
2284e81a9076SMaciej S. Szmigiero 		/* add additional settings */
2285e81a9076SMaciej S. Szmigiero 		cx25840_vconfig_add(state, val);
228610a34367SMauro Carvalho Chehab 	} else {
228710a34367SMauro Carvalho Chehab 		/* TODO: generic mode needs to be developed for other chips */
2288e81a9076SMaciej S. Szmigiero 		WARN_ON(1);
228910a34367SMauro Carvalho Chehab 	}
2290e81a9076SMaciej S. Szmigiero 
2291e81a9076SMaciej S. Szmigiero 	return 0;
2292e81a9076SMaciej S. Szmigiero }
2293e81a9076SMaciej S. Szmigiero 
cx25840_reset(struct v4l2_subdev * sd,u32 val)2294ccf7a31fSMaciej S. Szmigiero static int cx25840_reset(struct v4l2_subdev *sd, u32 val)
2295bd985160SHans Verkuil {
22969357b31cSHans Verkuil 	struct cx25840_state *state = to_state(sd);
22979357b31cSHans Verkuil 	struct i2c_client *client = v4l2_get_subdevdata(sd);
2298c976bc82SHans Verkuil 
22992a03f034SAndy Walls 	if (is_cx2583x(state))
2300c976bc82SHans Verkuil 		cx25836_initialize(client);
23012a03f034SAndy Walls 	else if (is_cx2388x(state))
2302f234081bSSteven Toth 		cx23885_initialize(client);
23032a03f034SAndy Walls 	else if (is_cx231xx(state))
2304149783b5SSri Deevi 		cx231xx_initialize(client);
2305c976bc82SHans Verkuil 	else
230689fc4eb9SHans Verkuil 		cx25840_initialize(client);
2307ccf7a31fSMaciej S. Szmigiero 
2308ccf7a31fSMaciej S. Szmigiero 	state->is_initialized = 1;
2309ccf7a31fSMaciej S. Szmigiero 
2310ccf7a31fSMaciej S. Szmigiero 	return 0;
2311ccf7a31fSMaciej S. Szmigiero }
2312ccf7a31fSMaciej S. Szmigiero 
2313ccf7a31fSMaciej S. Szmigiero /*
2314ccf7a31fSMaciej S. Szmigiero  * This load_fw operation must be called to load the driver's firmware.
2315ccf7a31fSMaciej S. Szmigiero  * This will load the firmware on the first invocation (further ones are NOP).
2316ccf7a31fSMaciej S. Szmigiero  * Without this the audio standard detection will fail and you will
2317ccf7a31fSMaciej S. Szmigiero  * only get mono.
2318ccf7a31fSMaciej S. Szmigiero  * Alternatively, you can call the reset operation instead of this one.
2319ccf7a31fSMaciej S. Szmigiero  *
2320ccf7a31fSMaciej S. Szmigiero  * Since loading the firmware is often problematic when the driver is
2321ccf7a31fSMaciej S. Szmigiero  * compiled into the kernel I recommend postponing calling this function
2322ccf7a31fSMaciej S. Szmigiero  * until the first open of the video device. Another reason for
2323ccf7a31fSMaciej S. Szmigiero  * postponing it is that loading this firmware takes a long time (seconds)
2324ccf7a31fSMaciej S. Szmigiero  * due to the slow i2c bus speed. So it will speed up the boot process if
2325ccf7a31fSMaciej S. Szmigiero  * you can avoid loading the fw as long as the video device isn't used.
2326ccf7a31fSMaciej S. Szmigiero  */
cx25840_load_fw(struct v4l2_subdev * sd)2327ccf7a31fSMaciej S. Szmigiero static int cx25840_load_fw(struct v4l2_subdev *sd)
2328ccf7a31fSMaciej S. Szmigiero {
2329ccf7a31fSMaciej S. Szmigiero 	struct cx25840_state *state = to_state(sd);
2330ccf7a31fSMaciej S. Szmigiero 
2331ccf7a31fSMaciej S. Szmigiero 	if (!state->is_initialized) {
2332ccf7a31fSMaciej S. Szmigiero 		/* initialize and load firmware */
2333ccf7a31fSMaciej S. Szmigiero 		cx25840_reset(sd, 0);
2334c976bc82SHans Verkuil 	}
23359357b31cSHans Verkuil 	return 0;
23369357b31cSHans Verkuil }
2337c976bc82SHans Verkuil 
2338bd985160SHans Verkuil #ifdef CONFIG_VIDEO_ADV_DEBUG
cx25840_g_register(struct v4l2_subdev * sd,struct v4l2_dbg_register * reg)233910a34367SMauro Carvalho Chehab static int cx25840_g_register(struct v4l2_subdev *sd,
234010a34367SMauro Carvalho Chehab 			      struct v4l2_dbg_register *reg)
2341bd985160SHans Verkuil {
23429357b31cSHans Verkuil 	struct i2c_client *client = v4l2_get_subdevdata(sd);
2343bd985160SHans Verkuil 
2344aecde8b5SHans Verkuil 	reg->size = 1;
234562d50addSTrent Piepho 	reg->val = cx25840_read(client, reg->reg & 0x0fff);
23469357b31cSHans Verkuil 	return 0;
23479357b31cSHans Verkuil }
23489357b31cSHans Verkuil 
cx25840_s_register(struct v4l2_subdev * sd,const struct v4l2_dbg_register * reg)234910a34367SMauro Carvalho Chehab static int cx25840_s_register(struct v4l2_subdev *sd,
235010a34367SMauro Carvalho Chehab 			      const struct v4l2_dbg_register *reg)
23519357b31cSHans Verkuil {
23529357b31cSHans Verkuil 	struct i2c_client *client = v4l2_get_subdevdata(sd);
23539357b31cSHans Verkuil 
2354bd985160SHans Verkuil 	cx25840_write(client, reg->reg & 0x0fff, reg->val & 0xff);
23559357b31cSHans Verkuil 	return 0;
2356bd985160SHans Verkuil }
2357bd985160SHans Verkuil #endif
2358bd985160SHans Verkuil 
cx25840_s_audio_stream(struct v4l2_subdev * sd,int enable)23593ccc646bSAndy Walls static int cx25840_s_audio_stream(struct v4l2_subdev *sd, int enable)
23603ccc646bSAndy Walls {
23613ccc646bSAndy Walls 	struct cx25840_state *state = to_state(sd);
23623ccc646bSAndy Walls 	struct i2c_client *client = v4l2_get_subdevdata(sd);
23633ccc646bSAndy Walls 	u8 v;
23643ccc646bSAndy Walls 
23653ccc646bSAndy Walls 	if (is_cx2583x(state) || is_cx2388x(state) || is_cx231xx(state))
23663ccc646bSAndy Walls 		return 0;
23673ccc646bSAndy Walls 
23683ccc646bSAndy Walls 	v4l_dbg(1, cx25840_debug, client, "%s audio output\n",
23693ccc646bSAndy Walls 		enable ? "enable" : "disable");
23703ccc646bSAndy Walls 
23713ccc646bSAndy Walls 	if (enable) {
23723ccc646bSAndy Walls 		v = cx25840_read(client, 0x115) | 0x80;
23733ccc646bSAndy Walls 		cx25840_write(client, 0x115, v);
23743ccc646bSAndy Walls 		v = cx25840_read(client, 0x116) | 0x03;
23753ccc646bSAndy Walls 		cx25840_write(client, 0x116, v);
23763ccc646bSAndy Walls 	} else {
23773ccc646bSAndy Walls 		v = cx25840_read(client, 0x115) & ~(0x80);
23783ccc646bSAndy Walls 		cx25840_write(client, 0x115, v);
23793ccc646bSAndy Walls 		v = cx25840_read(client, 0x116) & ~(0x03);
23803ccc646bSAndy Walls 		cx25840_write(client, 0x116, v);
23813ccc646bSAndy Walls 	}
23823ccc646bSAndy Walls 	return 0;
23833ccc646bSAndy Walls }
23843ccc646bSAndy Walls 
cx25840_s_stream(struct v4l2_subdev * sd,int enable)23859357b31cSHans Verkuil static int cx25840_s_stream(struct v4l2_subdev *sd, int enable)
23869357b31cSHans Verkuil {
23879357b31cSHans Verkuil 	struct cx25840_state *state = to_state(sd);
23889357b31cSHans Verkuil 	struct i2c_client *client = v4l2_get_subdevdata(sd);
23893ccc646bSAndy Walls 	u8 v;
23909357b31cSHans Verkuil 
23913ccc646bSAndy Walls 	v4l_dbg(1, cx25840_debug, client, "%s video output\n",
23929357b31cSHans Verkuil 		enable ? "enable" : "disable");
2393e69d8942SHans Verkuil 
2394e69d8942SHans Verkuil 	/*
2395e69d8942SHans Verkuil 	 * It's not clear what should be done for these devices.
2396e69d8942SHans Verkuil 	 * The original code used the same addresses as for the cx25840, but
2397e69d8942SHans Verkuil 	 * those addresses do something else entirely on the cx2388x and
2398e69d8942SHans Verkuil 	 * cx231xx. Since it never did anything in the first place, just do
2399e69d8942SHans Verkuil 	 * nothing.
2400e69d8942SHans Verkuil 	 */
2401e69d8942SHans Verkuil 	if (is_cx2388x(state) || is_cx231xx(state))
2402e69d8942SHans Verkuil 		return 0;
2403e69d8942SHans Verkuil 
24049357b31cSHans Verkuil 	if (enable) {
24053ccc646bSAndy Walls 		v = cx25840_read(client, 0x115) | 0x0c;
24063ccc646bSAndy Walls 		cx25840_write(client, 0x115, v);
24073ccc646bSAndy Walls 		v = cx25840_read(client, 0x116) | 0x04;
24083ccc646bSAndy Walls 		cx25840_write(client, 0x116, v);
2409f234081bSSteven Toth 	} else {
24103ccc646bSAndy Walls 		v = cx25840_read(client, 0x115) & ~(0x0c);
24113ccc646bSAndy Walls 		cx25840_write(client, 0x115, v);
24123ccc646bSAndy Walls 		v = cx25840_read(client, 0x116) & ~(0x04);
24133ccc646bSAndy Walls 		cx25840_write(client, 0x116, v);
2414f234081bSSteven Toth 	}
24159357b31cSHans Verkuil 	return 0;
24169357b31cSHans Verkuil }
2417bd985160SHans Verkuil 
241851ada787SSteven Toth /* Query the current detected video format */
cx25840_querystd(struct v4l2_subdev * sd,v4l2_std_id * std)241960acc4abSMaciej S. Szmigiero static int cx25840_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
242051ada787SSteven Toth {
242151ada787SSteven Toth 	struct i2c_client *client = v4l2_get_subdevdata(sd);
242251ada787SSteven Toth 
24232be730b8SColin Ian King 	static const v4l2_std_id stds[] = {
242451ada787SSteven Toth 		/* 0000 */ V4L2_STD_UNKNOWN,
242551ada787SSteven Toth 
242651ada787SSteven Toth 		/* 0001 */ V4L2_STD_NTSC_M,
242751ada787SSteven Toth 		/* 0010 */ V4L2_STD_NTSC_M_JP,
242851ada787SSteven Toth 		/* 0011 */ V4L2_STD_NTSC_443,
242951ada787SSteven Toth 		/* 0100 */ V4L2_STD_PAL,
243051ada787SSteven Toth 		/* 0101 */ V4L2_STD_PAL_M,
243151ada787SSteven Toth 		/* 0110 */ V4L2_STD_PAL_N,
243251ada787SSteven Toth 		/* 0111 */ V4L2_STD_PAL_Nc,
243351ada787SSteven Toth 		/* 1000 */ V4L2_STD_PAL_60,
243451ada787SSteven Toth 
243551ada787SSteven Toth 		/* 1001 */ V4L2_STD_UNKNOWN,
243651ada787SSteven Toth 		/* 1010 */ V4L2_STD_UNKNOWN,
243751ada787SSteven Toth 		/* 1011 */ V4L2_STD_UNKNOWN,
24387ff06130SMaciej S. Szmigiero 		/* 1100 */ V4L2_STD_SECAM,
24397ff06130SMaciej S. Szmigiero 		/* 1101 */ V4L2_STD_UNKNOWN,
244051ada787SSteven Toth 		/* 1110 */ V4L2_STD_UNKNOWN,
244151ada787SSteven Toth 		/* 1111 */ V4L2_STD_UNKNOWN
244251ada787SSteven Toth 	};
244351ada787SSteven Toth 
244451ada787SSteven Toth 	u32 fmt = (cx25840_read4(client, 0x40c) >> 8) & 0xf;
244551ada787SSteven Toth 	*std = stds[fmt];
244651ada787SSteven Toth 
244760acc4abSMaciej S. Szmigiero 	v4l_dbg(1, cx25840_debug, client,
244860acc4abSMaciej S. Szmigiero 		"querystd fmt = %x, v4l2_std_id = 0x%x\n",
244951ada787SSteven Toth 		fmt, (unsigned int)stds[fmt]);
245051ada787SSteven Toth 
245151ada787SSteven Toth 	return 0;
245251ada787SSteven Toth }
245351ada787SSteven Toth 
cx25840_g_input_status(struct v4l2_subdev * sd,u32 * status)2454a21df45dSSteven Toth static int cx25840_g_input_status(struct v4l2_subdev *sd, u32 *status)
2455a21df45dSSteven Toth {
2456a21df45dSSteven Toth 	struct i2c_client *client = v4l2_get_subdevdata(sd);
2457a21df45dSSteven Toth 
245810a34367SMauro Carvalho Chehab 	/*
245910a34367SMauro Carvalho Chehab 	 * A limited function that checks for signal status and returns
2460a21df45dSSteven Toth 	 * the state.
2461a21df45dSSteven Toth 	 */
2462a21df45dSSteven Toth 
2463a21df45dSSteven Toth 	/* Check for status of Horizontal lock (SRC lock isn't reliable) */
2464a21df45dSSteven Toth 	if ((cx25840_read4(client, 0x40c) & 0x00010000) == 0)
2465a21df45dSSteven Toth 		*status |= V4L2_IN_ST_NO_SIGNAL;
2466a21df45dSSteven Toth 
2467a21df45dSSteven Toth 	return 0;
2468a21df45dSSteven Toth }
2469a21df45dSSteven Toth 
cx25840_g_std(struct v4l2_subdev * sd,v4l2_std_id * std)2470763549a3SMaciej S. Szmigiero static int cx25840_g_std(struct v4l2_subdev *sd, v4l2_std_id *std)
2471763549a3SMaciej S. Szmigiero {
2472763549a3SMaciej S. Szmigiero 	struct cx25840_state *state = to_state(sd);
2473763549a3SMaciej S. Szmigiero 
2474763549a3SMaciej S. Szmigiero 	*std = state->std;
2475763549a3SMaciej S. Szmigiero 
2476763549a3SMaciej S. Szmigiero 	return 0;
2477763549a3SMaciej S. Szmigiero }
2478763549a3SMaciej S. Szmigiero 
cx25840_s_std(struct v4l2_subdev * sd,v4l2_std_id std)24799357b31cSHans Verkuil static int cx25840_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
24809357b31cSHans Verkuil {
24819357b31cSHans Verkuil 	struct cx25840_state *state = to_state(sd);
24829357b31cSHans Verkuil 	struct i2c_client *client = v4l2_get_subdevdata(sd);
2483bd985160SHans Verkuil 
24849357b31cSHans Verkuil 	if (state->radio == 0 && state->std == std)
2485081b496aSHans Verkuil 		return 0;
24863faeeae4SHans Verkuil 	state->radio = 0;
24879357b31cSHans Verkuil 	state->std = std;
2488081b496aSHans Verkuil 	return set_v4lstd(client);
24899357b31cSHans Verkuil }
24903faeeae4SHans Verkuil 
cx25840_s_radio(struct v4l2_subdev * sd)24919357b31cSHans Verkuil static int cx25840_s_radio(struct v4l2_subdev *sd)
24929357b31cSHans Verkuil {
24939357b31cSHans Verkuil 	struct cx25840_state *state = to_state(sd);
24949357b31cSHans Verkuil 
24953faeeae4SHans Verkuil 	state->radio = 1;
24969357b31cSHans Verkuil 	return 0;
24979357b31cSHans Verkuil }
2498bd985160SHans Verkuil 
cx25840_s_video_routing(struct v4l2_subdev * sd,u32 input,u32 output,u32 config)24995325b427SHans Verkuil static int cx25840_s_video_routing(struct v4l2_subdev *sd,
25005325b427SHans Verkuil 				   u32 input, u32 output, u32 config)
25019357b31cSHans Verkuil {
25029357b31cSHans Verkuil 	struct cx25840_state *state = to_state(sd);
25039357b31cSHans Verkuil 	struct i2c_client *client = v4l2_get_subdevdata(sd);
2504bd985160SHans Verkuil 
2505ba50e7e1SDevin Heitmueller 	if (is_cx23888(state))
2506ba50e7e1SDevin Heitmueller 		cx23888_std_setup(client);
250774900b47SSteven Toth 
2508e81a9076SMaciej S. Szmigiero 	if (is_cx2584x(state) && state->generic_mode && config) {
2509e81a9076SMaciej S. Szmigiero 		cx25840_vconfig_add(state, config);
2510e81a9076SMaciej S. Szmigiero 		cx25840_vconfig_apply(client);
2511e81a9076SMaciej S. Szmigiero 	}
2512e81a9076SMaciej S. Szmigiero 
25135325b427SHans Verkuil 	return set_input(client, input, state->aud_input);
25149357b31cSHans Verkuil }
2515bd985160SHans Verkuil 
cx25840_s_audio_routing(struct v4l2_subdev * sd,u32 input,u32 output,u32 config)25165325b427SHans Verkuil static int cx25840_s_audio_routing(struct v4l2_subdev *sd,
25175325b427SHans Verkuil 				   u32 input, u32 output, u32 config)
25189357b31cSHans Verkuil {
25199357b31cSHans Verkuil 	struct cx25840_state *state = to_state(sd);
25209357b31cSHans Verkuil 	struct i2c_client *client = v4l2_get_subdevdata(sd);
2521a8bbf12aSHans Verkuil 
2522ba50e7e1SDevin Heitmueller 	if (is_cx23888(state))
2523ba50e7e1SDevin Heitmueller 		cx23888_std_setup(client);
25245325b427SHans Verkuil 	return set_input(client, state->vid_input, input);
2525e2b8cf4cSHans Verkuil }
2526bd985160SHans Verkuil 
cx25840_s_frequency(struct v4l2_subdev * sd,const struct v4l2_frequency * freq)252710a34367SMauro Carvalho Chehab static int cx25840_s_frequency(struct v4l2_subdev *sd,
252810a34367SMauro Carvalho Chehab 			       const struct v4l2_frequency *freq)
2529bd985160SHans Verkuil {
25309357b31cSHans Verkuil 	struct i2c_client *client = v4l2_get_subdevdata(sd);
25319357b31cSHans Verkuil 
25329357b31cSHans Verkuil 	input_change(client);
25339357b31cSHans Verkuil 	return 0;
25349357b31cSHans Verkuil }
25359357b31cSHans Verkuil 
cx25840_g_tuner(struct v4l2_subdev * sd,struct v4l2_tuner * vt)25369357b31cSHans Verkuil static int cx25840_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
25379357b31cSHans Verkuil {
25389357b31cSHans Verkuil 	struct cx25840_state *state = to_state(sd);
25399357b31cSHans Verkuil 	struct i2c_client *client = v4l2_get_subdevdata(sd);
2540e2b8cf4cSHans Verkuil 	u8 vpres = cx25840_read(client, 0x40e) & 0x20;
2541e2b8cf4cSHans Verkuil 	u8 mode;
2542bd985160SHans Verkuil 	int val = 0;
2543bd985160SHans Verkuil 
25443faeeae4SHans Verkuil 	if (state->radio)
25459357b31cSHans Verkuil 		return 0;
25463faeeae4SHans Verkuil 
2547e2b8cf4cSHans Verkuil 	vt->signal = vpres ? 0xffff : 0x0;
25482a03f034SAndy Walls 	if (is_cx2583x(state))
25499357b31cSHans Verkuil 		return 0;
2550e2b8cf4cSHans Verkuil 
255110a34367SMauro Carvalho Chehab 	vt->capability |= V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
2552bd985160SHans Verkuil 			  V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
2553bd985160SHans Verkuil 
2554e2b8cf4cSHans Verkuil 	mode = cx25840_read(client, 0x804);
2555bd985160SHans Verkuil 
2556bd985160SHans Verkuil 	/* get rxsubchans and audmode */
2557bd985160SHans Verkuil 	if ((mode & 0xf) == 1)
2558bd985160SHans Verkuil 		val |= V4L2_TUNER_SUB_STEREO;
2559bd985160SHans Verkuil 	else
2560bd985160SHans Verkuil 		val |= V4L2_TUNER_SUB_MONO;
2561bd985160SHans Verkuil 
2562bd985160SHans Verkuil 	if (mode == 2 || mode == 4)
25638a4b275fSHans Verkuil 		val = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
2564bd985160SHans Verkuil 
2565bd985160SHans Verkuil 	if (mode & 0x10)
2566bd985160SHans Verkuil 		val |= V4L2_TUNER_SUB_SAP;
2567bd985160SHans Verkuil 
2568bd985160SHans Verkuil 	vt->rxsubchans = val;
25698a4b275fSHans Verkuil 	vt->audmode = state->audmode;
25709357b31cSHans Verkuil 	return 0;
2571bd985160SHans Verkuil }
2572bd985160SHans Verkuil 
cx25840_s_tuner(struct v4l2_subdev * sd,const struct v4l2_tuner * vt)25732f73c7c5SHans Verkuil static int cx25840_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt)
25749357b31cSHans Verkuil {
25759357b31cSHans Verkuil 	struct cx25840_state *state = to_state(sd);
25769357b31cSHans Verkuil 	struct i2c_client *client = v4l2_get_subdevdata(sd);
25779357b31cSHans Verkuil 
25782a03f034SAndy Walls 	if (state->radio || is_cx2583x(state))
25799357b31cSHans Verkuil 		return 0;
25808a4b275fSHans Verkuil 
2581bd985160SHans Verkuil 	switch (vt->audmode) {
2582bd985160SHans Verkuil 	case V4L2_TUNER_MODE_MONO:
258310a34367SMauro Carvalho Chehab 		/*
258410a34367SMauro Carvalho Chehab 		 * mono      -> mono
258510a34367SMauro Carvalho Chehab 		 * stereo    -> mono
258610a34367SMauro Carvalho Chehab 		 * bilingual -> lang1
258710a34367SMauro Carvalho Chehab 		 */
2588bd985160SHans Verkuil 		cx25840_and_or(client, 0x809, ~0xf, 0x00);
2589bd985160SHans Verkuil 		break;
2590301e22d6SHans Verkuil 	case V4L2_TUNER_MODE_STEREO:
25918a4b275fSHans Verkuil 	case V4L2_TUNER_MODE_LANG1:
259210a34367SMauro Carvalho Chehab 		/*
259310a34367SMauro Carvalho Chehab 		 * mono      -> mono
259410a34367SMauro Carvalho Chehab 		 * stereo    -> stereo
259510a34367SMauro Carvalho Chehab 		 * bilingual -> lang1
259610a34367SMauro Carvalho Chehab 		 */
2597bd985160SHans Verkuil 		cx25840_and_or(client, 0x809, ~0xf, 0x04);
2598bd985160SHans Verkuil 		break;
2599301e22d6SHans Verkuil 	case V4L2_TUNER_MODE_LANG1_LANG2:
260010a34367SMauro Carvalho Chehab 		/*
260110a34367SMauro Carvalho Chehab 		 * mono      -> mono
260210a34367SMauro Carvalho Chehab 		 * stereo    -> stereo
260310a34367SMauro Carvalho Chehab 		 * bilingual -> lang1/lang2
260410a34367SMauro Carvalho Chehab 		 */
26058a4b275fSHans Verkuil 		cx25840_and_or(client, 0x809, ~0xf, 0x07);
26068a4b275fSHans Verkuil 		break;
2607bd985160SHans Verkuil 	case V4L2_TUNER_MODE_LANG2:
260810a34367SMauro Carvalho Chehab 		/*
260910a34367SMauro Carvalho Chehab 		 * mono      -> mono
261010a34367SMauro Carvalho Chehab 		 * stereo    -> stereo
261110a34367SMauro Carvalho Chehab 		 * bilingual -> lang2
261210a34367SMauro Carvalho Chehab 		 */
2613bd985160SHans Verkuil 		cx25840_and_or(client, 0x809, ~0xf, 0x01);
2614bd985160SHans Verkuil 		break;
26158a4b275fSHans Verkuil 	default:
26168a4b275fSHans Verkuil 		return -EINVAL;
2617bd985160SHans Verkuil 	}
26188a4b275fSHans Verkuil 	state->audmode = vt->audmode;
26199357b31cSHans Verkuil 	return 0;
26209357b31cSHans Verkuil }
2621bd985160SHans Verkuil 
cx25840_log_status(struct v4l2_subdev * sd)26229357b31cSHans Verkuil static int cx25840_log_status(struct v4l2_subdev *sd)
26239357b31cSHans Verkuil {
26249357b31cSHans Verkuil 	struct cx25840_state *state = to_state(sd);
26259357b31cSHans Verkuil 	struct i2c_client *client = v4l2_get_subdevdata(sd);
26269357b31cSHans Verkuil 
26279357b31cSHans Verkuil 	log_video_status(client);
26282a03f034SAndy Walls 	if (!is_cx2583x(state))
26299357b31cSHans Verkuil 		log_audio_status(client);
263052fd3ddaSAndy Walls 	cx25840_ir_log_status(sd);
2631e34e658bSHans Verkuil 	v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
26329357b31cSHans Verkuil 	return 0;
26339357b31cSHans Verkuil }
26349357b31cSHans Verkuil 
cx23885_irq_handler(struct v4l2_subdev * sd,u32 status,bool * handled)263552fd3ddaSAndy Walls static int cx23885_irq_handler(struct v4l2_subdev *sd, u32 status,
263652fd3ddaSAndy Walls 			       bool *handled)
263752fd3ddaSAndy Walls {
263852fd3ddaSAndy Walls 	struct cx25840_state *state = to_state(sd);
263952fd3ddaSAndy Walls 	struct i2c_client *c = v4l2_get_subdevdata(sd);
264052fd3ddaSAndy Walls 	u8 irq_stat, aud_stat, aud_en, ir_stat, ir_en;
264152fd3ddaSAndy Walls 	u32 vid_stat, aud_mc_stat;
264252fd3ddaSAndy Walls 	bool block_handled;
264352fd3ddaSAndy Walls 	int ret = 0;
264452fd3ddaSAndy Walls 
264552fd3ddaSAndy Walls 	irq_stat = cx25840_read(c, CX23885_PIN_CTRL_IRQ_REG);
264652fd3ddaSAndy Walls 	v4l_dbg(2, cx25840_debug, c, "AV Core IRQ status (entry): %s %s %s\n",
264752fd3ddaSAndy Walls 		irq_stat & CX23885_PIN_CTRL_IRQ_IR_STAT ? "ir" : "  ",
264852fd3ddaSAndy Walls 		irq_stat & CX23885_PIN_CTRL_IRQ_AUD_STAT ? "aud" : "   ",
264952fd3ddaSAndy Walls 		irq_stat & CX23885_PIN_CTRL_IRQ_VID_STAT ? "vid" : "   ");
265052fd3ddaSAndy Walls 
265152fd3ddaSAndy Walls 	if ((is_cx23885(state) || is_cx23887(state))) {
265252fd3ddaSAndy Walls 		ir_stat = cx25840_read(c, CX25840_IR_STATS_REG);
265352fd3ddaSAndy Walls 		ir_en = cx25840_read(c, CX25840_IR_IRQEN_REG);
265452fd3ddaSAndy Walls 		v4l_dbg(2, cx25840_debug, c,
265552fd3ddaSAndy Walls 			"AV Core ir IRQ status: %#04x disables: %#04x\n",
265652fd3ddaSAndy Walls 			ir_stat, ir_en);
265752fd3ddaSAndy Walls 		if (irq_stat & CX23885_PIN_CTRL_IRQ_IR_STAT) {
265852fd3ddaSAndy Walls 			block_handled = false;
265952fd3ddaSAndy Walls 			ret = cx25840_ir_irq_handler(sd,
266052fd3ddaSAndy Walls 						     status, &block_handled);
266152fd3ddaSAndy Walls 			if (block_handled)
266252fd3ddaSAndy Walls 				*handled = true;
266352fd3ddaSAndy Walls 		}
266452fd3ddaSAndy Walls 	}
266552fd3ddaSAndy Walls 
266652fd3ddaSAndy Walls 	aud_stat = cx25840_read(c, CX25840_AUD_INT_STAT_REG);
266752fd3ddaSAndy Walls 	aud_en = cx25840_read(c, CX25840_AUD_INT_CTRL_REG);
266852fd3ddaSAndy Walls 	v4l_dbg(2, cx25840_debug, c,
266952fd3ddaSAndy Walls 		"AV Core audio IRQ status: %#04x disables: %#04x\n",
267052fd3ddaSAndy Walls 		aud_stat, aud_en);
267152fd3ddaSAndy Walls 	aud_mc_stat = cx25840_read4(c, CX23885_AUD_MC_INT_MASK_REG);
267252fd3ddaSAndy Walls 	v4l_dbg(2, cx25840_debug, c,
267352fd3ddaSAndy Walls 		"AV Core audio MC IRQ status: %#06x enables: %#06x\n",
267452fd3ddaSAndy Walls 		aud_mc_stat >> CX23885_AUD_MC_INT_STAT_SHFT,
267552fd3ddaSAndy Walls 		aud_mc_stat & CX23885_AUD_MC_INT_CTRL_BITS);
267652fd3ddaSAndy Walls 	if (irq_stat & CX23885_PIN_CTRL_IRQ_AUD_STAT) {
267752fd3ddaSAndy Walls 		if (aud_stat) {
267852fd3ddaSAndy Walls 			cx25840_write(c, CX25840_AUD_INT_STAT_REG, aud_stat);
267952fd3ddaSAndy Walls 			*handled = true;
268052fd3ddaSAndy Walls 		}
268152fd3ddaSAndy Walls 	}
268252fd3ddaSAndy Walls 
268352fd3ddaSAndy Walls 	vid_stat = cx25840_read4(c, CX25840_VID_INT_STAT_REG);
268452fd3ddaSAndy Walls 	v4l_dbg(2, cx25840_debug, c,
268552fd3ddaSAndy Walls 		"AV Core video IRQ status: %#06x disables: %#06x\n",
268652fd3ddaSAndy Walls 		vid_stat & CX25840_VID_INT_STAT_BITS,
268752fd3ddaSAndy Walls 		vid_stat >> CX25840_VID_INT_MASK_SHFT);
268852fd3ddaSAndy Walls 	if (irq_stat & CX23885_PIN_CTRL_IRQ_VID_STAT) {
268952fd3ddaSAndy Walls 		if (vid_stat & CX25840_VID_INT_STAT_BITS) {
269052fd3ddaSAndy Walls 			cx25840_write4(c, CX25840_VID_INT_STAT_REG, vid_stat);
269152fd3ddaSAndy Walls 			*handled = true;
269252fd3ddaSAndy Walls 		}
269352fd3ddaSAndy Walls 	}
269452fd3ddaSAndy Walls 
269552fd3ddaSAndy Walls 	irq_stat = cx25840_read(c, CX23885_PIN_CTRL_IRQ_REG);
269652fd3ddaSAndy Walls 	v4l_dbg(2, cx25840_debug, c, "AV Core IRQ status (exit): %s %s %s\n",
269752fd3ddaSAndy Walls 		irq_stat & CX23885_PIN_CTRL_IRQ_IR_STAT ? "ir" : "  ",
269852fd3ddaSAndy Walls 		irq_stat & CX23885_PIN_CTRL_IRQ_AUD_STAT ? "aud" : "   ",
269952fd3ddaSAndy Walls 		irq_stat & CX23885_PIN_CTRL_IRQ_VID_STAT ? "vid" : "   ");
270052fd3ddaSAndy Walls 
270152fd3ddaSAndy Walls 	return ret;
270252fd3ddaSAndy Walls }
270352fd3ddaSAndy Walls 
cx25840_irq_handler(struct v4l2_subdev * sd,u32 status,bool * handled)270452fd3ddaSAndy Walls static int cx25840_irq_handler(struct v4l2_subdev *sd, u32 status,
270552fd3ddaSAndy Walls 			       bool *handled)
270652fd3ddaSAndy Walls {
270752fd3ddaSAndy Walls 	struct cx25840_state *state = to_state(sd);
270852fd3ddaSAndy Walls 
270952fd3ddaSAndy Walls 	*handled = false;
271052fd3ddaSAndy Walls 
271152fd3ddaSAndy Walls 	/* Only support the CX2388[578] AV Core for now */
271252fd3ddaSAndy Walls 	if (is_cx2388x(state))
271352fd3ddaSAndy Walls 		return cx23885_irq_handler(sd, status, handled);
271452fd3ddaSAndy Walls 
271552fd3ddaSAndy Walls 	return -ENODEV;
271652fd3ddaSAndy Walls }
271752fd3ddaSAndy Walls 
27189357b31cSHans Verkuil /* ----------------------------------------------------------------------- */
27199357b31cSHans Verkuil 
272074900b47SSteven Toth #define DIF_PLL_FREQ_WORD	(0x300)
272174900b47SSteven Toth #define DIF_BPF_COEFF01		(0x348)
272274900b47SSteven Toth #define DIF_BPF_COEFF23		(0x34c)
272374900b47SSteven Toth #define DIF_BPF_COEFF45		(0x350)
272474900b47SSteven Toth #define DIF_BPF_COEFF67		(0x354)
272574900b47SSteven Toth #define DIF_BPF_COEFF89		(0x358)
272674900b47SSteven Toth #define DIF_BPF_COEFF1011	(0x35c)
272774900b47SSteven Toth #define DIF_BPF_COEFF1213	(0x360)
272874900b47SSteven Toth #define DIF_BPF_COEFF1415	(0x364)
272974900b47SSteven Toth #define DIF_BPF_COEFF1617	(0x368)
273074900b47SSteven Toth #define DIF_BPF_COEFF1819	(0x36c)
273174900b47SSteven Toth #define DIF_BPF_COEFF2021	(0x370)
273274900b47SSteven Toth #define DIF_BPF_COEFF2223	(0x374)
273374900b47SSteven Toth #define DIF_BPF_COEFF2425	(0x378)
273474900b47SSteven Toth #define DIF_BPF_COEFF2627	(0x37c)
273574900b47SSteven Toth #define DIF_BPF_COEFF2829	(0x380)
273674900b47SSteven Toth #define DIF_BPF_COEFF3031	(0x384)
273774900b47SSteven Toth #define DIF_BPF_COEFF3233	(0x388)
273874900b47SSteven Toth #define DIF_BPF_COEFF3435	(0x38c)
273974900b47SSteven Toth #define DIF_BPF_COEFF36		(0x390)
274074900b47SSteven Toth 
274157a3afc5SHans Verkuil static const u32 ifhz_coeffs[][19] = {
274257a3afc5SHans Verkuil 	{	// 3.0 MHz
274357a3afc5SHans Verkuil 		0x00000002, 0x00080012, 0x001e0024, 0x001bfff8,
274457a3afc5SHans Verkuil 		0xffb4ff50, 0xfed8fe68, 0xfe24fe34, 0xfebaffc7,
274557a3afc5SHans Verkuil 		0x014d031f, 0x04f0065d, 0x07010688, 0x04c901d6,
274657a3afc5SHans Verkuil 		0xfe00f9d3, 0xf600f342, 0xf235f337, 0xf64efb22,
274757a3afc5SHans Verkuil 		0x0105070f, 0x0c460fce, 0x110d0000,
274857a3afc5SHans Verkuil 	}, {	// 3.1 MHz
274957a3afc5SHans Verkuil 		0x00000001, 0x00070012, 0x00220032, 0x00370026,
275057a3afc5SHans Verkuil 		0xfff0ff91, 0xff0efe7c, 0xfe01fdcc, 0xfe0afedb,
275157a3afc5SHans Verkuil 		0x00440224, 0x0434060c, 0x0738074e, 0x06090361,
275257a3afc5SHans Verkuil 		0xff99fb39, 0xf6fef3b6, 0xf21af2a5, 0xf573fa33,
275357a3afc5SHans Verkuil 		0x0034067d, 0x0bfb0fb9, 0x110d0000,
275457a3afc5SHans Verkuil 	}, {	// 3.2 MHz
275557a3afc5SHans Verkuil 		0x00000000, 0x0004000e, 0x00200038, 0x004c004f,
275657a3afc5SHans Verkuil 		0x002fffdf, 0xff5cfeb6, 0xfe0dfd92, 0xfd7ffe03,
275757a3afc5SHans Verkuil 		0xff36010a, 0x03410575, 0x072607d2, 0x071804d5,
275857a3afc5SHans Verkuil 		0x0134fcb7, 0xf81ff451, 0xf223f22e, 0xf4a7f94b,
275957a3afc5SHans Verkuil 		0xff6405e8, 0x0bae0fa4, 0x110d0000,
276057a3afc5SHans Verkuil 	}, {	// 3.3 MHz
276157a3afc5SHans Verkuil 		0x0000ffff, 0x00000008, 0x001a0036, 0x0056006d,
276257a3afc5SHans Verkuil 		0x00670030, 0xffbdff10, 0xfe46fd8d, 0xfd25fd4f,
276357a3afc5SHans Verkuil 		0xfe35ffe0, 0x0224049f, 0x06c9080e, 0x07ef0627,
276457a3afc5SHans Verkuil 		0x02c9fe45, 0xf961f513, 0xf250f1d2, 0xf3ecf869,
276557a3afc5SHans Verkuil 		0xfe930552, 0x0b5f0f8f, 0x110d0000,
276657a3afc5SHans Verkuil 	}, {	// 3.4 MHz
276757a3afc5SHans Verkuil 		0xfffffffe, 0xfffd0001, 0x000f002c, 0x0054007d,
276857a3afc5SHans Verkuil 		0x0093007c, 0x0024ff82, 0xfea6fdbb, 0xfd03fcca,
276957a3afc5SHans Verkuil 		0xfd51feb9, 0x00eb0392, 0x06270802, 0x08880750,
277057a3afc5SHans Verkuil 		0x044dffdb, 0xfabdf5f8, 0xf2a0f193, 0xf342f78f,
277157a3afc5SHans Verkuil 		0xfdc404b9, 0x0b0e0f78, 0x110d0000,
277257a3afc5SHans Verkuil 	}, {	// 3.5 MHz
277357a3afc5SHans Verkuil 		0xfffffffd, 0xfffafff9, 0x0002001b, 0x0046007d,
277457a3afc5SHans Verkuil 		0x00ad00ba, 0x00870000, 0xff26fe1a, 0xfd1bfc7e,
277557a3afc5SHans Verkuil 		0xfc99fda4, 0xffa5025c, 0x054507ad, 0x08dd0847,
277657a3afc5SHans Verkuil 		0x05b80172, 0xfc2ef6ff, 0xf313f170, 0xf2abf6bd,
277757a3afc5SHans Verkuil 		0xfcf6041f, 0x0abc0f61, 0x110d0000,
277857a3afc5SHans Verkuil 	}, {	// 3.6 MHz
277957a3afc5SHans Verkuil 		0xfffffffd, 0xfff8fff3, 0xfff50006, 0x002f006c,
278057a3afc5SHans Verkuil 		0x00b200e3, 0x00dc007e, 0xffb9fea0, 0xfd6bfc71,
278157a3afc5SHans Verkuil 		0xfc17fcb1, 0xfe65010b, 0x042d0713, 0x08ec0906,
278257a3afc5SHans Verkuil 		0x07020302, 0xfdaff823, 0xf3a7f16a, 0xf228f5f5,
278357a3afc5SHans Verkuil 		0xfc2a0384, 0x0a670f4a, 0x110d0000,
278457a3afc5SHans Verkuil 	}, {	// 3.7 MHz
278557a3afc5SHans Verkuil 		0x0000fffd, 0xfff7ffef, 0xffe9fff1, 0x0010004d,
278657a3afc5SHans Verkuil 		0x00a100f2, 0x011a00f0, 0x0053ff44, 0xfdedfca2,
278757a3afc5SHans Verkuil 		0xfbd3fbef, 0xfd39ffae, 0x02ea0638, 0x08b50987,
278857a3afc5SHans Verkuil 		0x08230483, 0xff39f960, 0xf45bf180, 0xf1b8f537,
278957a3afc5SHans Verkuil 		0xfb6102e7, 0x0a110f32, 0x110d0000,
279057a3afc5SHans Verkuil 	}, {	// 3.8 MHz
279157a3afc5SHans Verkuil 		0x0000fffe, 0xfff9ffee, 0xffe1ffdd, 0xfff00024,
279257a3afc5SHans Verkuil 		0x007c00e5, 0x013a014a, 0x00e6fff8, 0xfe98fd0f,
279357a3afc5SHans Verkuil 		0xfbd3fb67, 0xfc32fe54, 0x01880525, 0x083909c7,
279457a3afc5SHans Verkuil 		0x091505ee, 0x00c7fab3, 0xf52df1b4, 0xf15df484,
279557a3afc5SHans Verkuil 		0xfa9b0249, 0x09ba0f19, 0x110d0000,
279657a3afc5SHans Verkuil 	}, {	// 3.9 MHz
279757a3afc5SHans Verkuil 		0x00000000, 0xfffbfff0, 0xffdeffcf, 0xffd1fff6,
279857a3afc5SHans Verkuil 		0x004800be, 0x01390184, 0x016300ac, 0xff5efdb1,
279957a3afc5SHans Verkuil 		0xfc17fb23, 0xfb5cfd0d, 0x001703e4, 0x077b09c4,
280057a3afc5SHans Verkuil 		0x09d2073c, 0x0251fc18, 0xf61cf203, 0xf118f3dc,
280157a3afc5SHans Verkuil 		0xf9d801aa, 0x09600eff, 0x110d0000,
280257a3afc5SHans Verkuil 	}, {	// 4.0 MHz
280357a3afc5SHans Verkuil 		0x00000001, 0xfffefff4, 0xffe1ffc8, 0xffbaffca,
280457a3afc5SHans Verkuil 		0x000b0082, 0x01170198, 0x01c10152, 0x0030fe7b,
280557a3afc5SHans Verkuil 		0xfc99fb24, 0xfac3fbe9, 0xfea5027f, 0x0683097f,
280657a3afc5SHans Verkuil 		0x0a560867, 0x03d2fd89, 0xf723f26f, 0xf0e8f341,
280757a3afc5SHans Verkuil 		0xf919010a, 0x09060ee5, 0x110d0000,
280857a3afc5SHans Verkuil 	}, {	// 4.1 MHz
280957a3afc5SHans Verkuil 		0x00010002, 0x0002fffb, 0xffe8ffca, 0xffacffa4,
281057a3afc5SHans Verkuil 		0xffcd0036, 0x00d70184, 0x01f601dc, 0x00ffff60,
281157a3afc5SHans Verkuil 		0xfd51fb6d, 0xfa6efaf5, 0xfd410103, 0x055708f9,
281257a3afc5SHans Verkuil 		0x0a9e0969, 0x0543ff02, 0xf842f2f5, 0xf0cef2b2,
281357a3afc5SHans Verkuil 		0xf85e006b, 0x08aa0ecb, 0x110d0000,
281457a3afc5SHans Verkuil 	}, {	// 4.2 MHz
281557a3afc5SHans Verkuil 		0x00010003, 0x00050003, 0xfff3ffd3, 0xffaaff8b,
281657a3afc5SHans Verkuil 		0xff95ffe5, 0x0080014a, 0x01fe023f, 0x01ba0050,
281757a3afc5SHans Verkuil 		0xfe35fbf8, 0xfa62fa3b, 0xfbf9ff7e, 0x04010836,
281857a3afc5SHans Verkuil 		0x0aa90a3d, 0x069f007f, 0xf975f395, 0xf0cbf231,
281957a3afc5SHans Verkuil 		0xf7a9ffcb, 0x084c0eaf, 0x110d0000,
282057a3afc5SHans Verkuil 	}, {	// 4.3 MHz
282157a3afc5SHans Verkuil 		0x00010003, 0x0008000a, 0x0000ffe4, 0xffb4ff81,
282257a3afc5SHans Verkuil 		0xff6aff96, 0x001c00f0, 0x01d70271, 0x0254013b,
282357a3afc5SHans Verkuil 		0xff36fcbd, 0xfa9ff9c5, 0xfadbfdfe, 0x028c073b,
282457a3afc5SHans Verkuil 		0x0a750adf, 0x07e101fa, 0xfab8f44e, 0xf0ddf1be,
282557a3afc5SHans Verkuil 		0xf6f9ff2b, 0x07ed0e94, 0x110d0000,
282657a3afc5SHans Verkuil 	}, {	// 4.4 MHz
282757a3afc5SHans Verkuil 		0x00000003, 0x0009000f, 0x000efff8, 0xffc9ff87,
282857a3afc5SHans Verkuil 		0xff52ff54, 0xffb5007e, 0x01860270, 0x02c00210,
282957a3afc5SHans Verkuil 		0x0044fdb2, 0xfb22f997, 0xf9f2fc90, 0x0102060f,
283057a3afc5SHans Verkuil 		0x0a050b4c, 0x0902036e, 0xfc0af51e, 0xf106f15a,
283157a3afc5SHans Verkuil 		0xf64efe8b, 0x078d0e77, 0x110d0000,
283257a3afc5SHans Verkuil 	}, {	// 4.5 MHz
283357a3afc5SHans Verkuil 		0x00000002, 0x00080012, 0x0019000e, 0xffe5ff9e,
283457a3afc5SHans Verkuil 		0xff4fff25, 0xff560000, 0x0112023b, 0x02f702c0,
283557a3afc5SHans Verkuil 		0x014dfec8, 0xfbe5f9b3, 0xf947fb41, 0xff7004b9,
283657a3afc5SHans Verkuil 		0x095a0b81, 0x0a0004d8, 0xfd65f603, 0xf144f104,
283757a3afc5SHans Verkuil 		0xf5aafdec, 0x072b0e5a, 0x110d0000,
283857a3afc5SHans Verkuil 	}, {	// 4.6 MHz
283957a3afc5SHans Verkuil 		0x00000001, 0x00060012, 0x00200022, 0x0005ffc1,
284057a3afc5SHans Verkuil 		0xff61ff10, 0xff09ff82, 0x008601d7, 0x02f50340,
284157a3afc5SHans Verkuil 		0x0241fff0, 0xfcddfa19, 0xf8e2fa1e, 0xfde30343,
284257a3afc5SHans Verkuil 		0x08790b7f, 0x0ad50631, 0xfec7f6fc, 0xf198f0bd,
284357a3afc5SHans Verkuil 		0xf50dfd4e, 0x06c90e3d, 0x110d0000,
284457a3afc5SHans Verkuil 	}, {	// 4.7 MHz
284557a3afc5SHans Verkuil 		0x0000ffff, 0x0003000f, 0x00220030, 0x0025ffed,
284657a3afc5SHans Verkuil 		0xff87ff15, 0xfed6ff10, 0xffed014c, 0x02b90386,
284757a3afc5SHans Verkuil 		0x03110119, 0xfdfefac4, 0xf8c6f92f, 0xfc6701b7,
284857a3afc5SHans Verkuil 		0x07670b44, 0x0b7e0776, 0x002df807, 0xf200f086,
284957a3afc5SHans Verkuil 		0xf477fcb1, 0x06650e1e, 0x110d0000,
285057a3afc5SHans Verkuil 	}, {	// 4.8 MHz
285157a3afc5SHans Verkuil 		0xfffffffe, 0xffff0009, 0x001e0038, 0x003f001b,
285257a3afc5SHans Verkuil 		0xffbcff36, 0xfec2feb6, 0xff5600a5, 0x0248038d,
285357a3afc5SHans Verkuil 		0x03b00232, 0xff39fbab, 0xf8f4f87f, 0xfb060020,
285457a3afc5SHans Verkuil 		0x062a0ad2, 0x0bf908a3, 0x0192f922, 0xf27df05e,
285557a3afc5SHans Verkuil 		0xf3e8fc14, 0x06000e00, 0x110d0000,
285657a3afc5SHans Verkuil 	}, {	// 4.9 MHz
285757a3afc5SHans Verkuil 		0xfffffffd, 0xfffc0002, 0x00160037, 0x00510046,
285857a3afc5SHans Verkuil 		0xfff9ff6d, 0xfed0fe7c, 0xfecefff0, 0x01aa0356,
285957a3afc5SHans Verkuil 		0x0413032b, 0x007ffcc5, 0xf96cf812, 0xf9cefe87,
286057a3afc5SHans Verkuil 		0x04c90a2c, 0x0c4309b4, 0x02f3fa4a, 0xf30ef046,
286157a3afc5SHans Verkuil 		0xf361fb7a, 0x059b0de0, 0x110d0000,
286257a3afc5SHans Verkuil 	}, {	// 5.0 MHz
286357a3afc5SHans Verkuil 		0xfffffffd, 0xfff9fffa, 0x000a002d, 0x00570067,
286457a3afc5SHans Verkuil 		0x0037ffb5, 0xfefffe68, 0xfe62ff3d, 0x00ec02e3,
286557a3afc5SHans Verkuil 		0x043503f6, 0x01befe05, 0xfa27f7ee, 0xf8c6fcf8,
286657a3afc5SHans Verkuil 		0x034c0954, 0x0c5c0aa4, 0x044cfb7e, 0xf3b1f03f,
286757a3afc5SHans Verkuil 		0xf2e2fae1, 0x05340dc0, 0x110d0000,
286857a3afc5SHans Verkuil 	}, {	// 5.1 MHz
286957a3afc5SHans Verkuil 		0x0000fffd, 0xfff8fff4, 0xfffd001e, 0x0051007b,
287057a3afc5SHans Verkuil 		0x006e0006, 0xff48fe7c, 0xfe1bfe9a, 0x001d023e,
287157a3afc5SHans Verkuil 		0x04130488, 0x02e6ff5b, 0xfb1ef812, 0xf7f7fb7f,
287257a3afc5SHans Verkuil 		0x01bc084e, 0x0c430b72, 0x059afcba, 0xf467f046,
287357a3afc5SHans Verkuil 		0xf26cfa4a, 0x04cd0da0, 0x110d0000,
287457a3afc5SHans Verkuil 	}, {	// 5.2 MHz
287557a3afc5SHans Verkuil 		0x0000fffe, 0xfff8ffef, 0xfff00009, 0x003f007f,
287657a3afc5SHans Verkuil 		0x00980056, 0xffa5feb6, 0xfe00fe15, 0xff4b0170,
287757a3afc5SHans Verkuil 		0x03b004d7, 0x03e800b9, 0xfc48f87f, 0xf768fa23,
287857a3afc5SHans Verkuil 		0x0022071f, 0x0bf90c1b, 0x06dafdfd, 0xf52df05e,
287957a3afc5SHans Verkuil 		0xf1fef9b5, 0x04640d7f, 0x110d0000,
288057a3afc5SHans Verkuil 	}, {	// 5.3 MHz
288157a3afc5SHans Verkuil 		0x0000ffff, 0xfff9ffee, 0xffe6fff3, 0x00250072,
288257a3afc5SHans Verkuil 		0x00af009c, 0x000cff10, 0xfe13fdb8, 0xfe870089,
288357a3afc5SHans Verkuil 		0x031104e1, 0x04b8020f, 0xfd98f92f, 0xf71df8f0,
288457a3afc5SHans Verkuil 		0xfe8805ce, 0x0b7e0c9c, 0x0808ff44, 0xf603f086,
288557a3afc5SHans Verkuil 		0xf19af922, 0x03fb0d5e, 0x110d0000,
288657a3afc5SHans Verkuil 	}, {	// 5.4 MHz
288757a3afc5SHans Verkuil 		0x00000001, 0xfffcffef, 0xffe0ffe0, 0x00050056,
288857a3afc5SHans Verkuil 		0x00b000d1, 0x0071ff82, 0xfe53fd8c, 0xfddfff99,
288957a3afc5SHans Verkuil 		0x024104a3, 0x054a034d, 0xff01fa1e, 0xf717f7ed,
289057a3afc5SHans Verkuil 		0xfcf50461, 0x0ad50cf4, 0x0921008d, 0xf6e7f0bd,
289157a3afc5SHans Verkuil 		0xf13ff891, 0x03920d3b, 0x110d0000,
289257a3afc5SHans Verkuil 	}, {	// 5.5 MHz
289357a3afc5SHans Verkuil 		0x00010002, 0xfffffff3, 0xffdeffd1, 0xffe5002f,
289457a3afc5SHans Verkuil 		0x009c00ed, 0x00cb0000, 0xfebafd94, 0xfd61feb0,
289557a3afc5SHans Verkuil 		0x014d0422, 0x05970464, 0x0074fb41, 0xf759f721,
289657a3afc5SHans Verkuil 		0xfb7502de, 0x0a000d21, 0x0a2201d4, 0xf7d9f104,
289757a3afc5SHans Verkuil 		0xf0edf804, 0x03280d19, 0x110d0000,
289857a3afc5SHans Verkuil 	}, {	// 5.6 MHz
289957a3afc5SHans Verkuil 		0x00010003, 0x0003fffa, 0xffe3ffc9, 0xffc90002,
290057a3afc5SHans Verkuil 		0x007500ef, 0x010e007e, 0xff3dfdcf, 0xfd16fddd,
290157a3afc5SHans Verkuil 		0x00440365, 0x059b0548, 0x01e3fc90, 0xf7dff691,
290257a3afc5SHans Verkuil 		0xfa0f014d, 0x09020d23, 0x0b0a0318, 0xf8d7f15a,
290357a3afc5SHans Verkuil 		0xf0a5f779, 0x02bd0cf6, 0x110d0000,
290457a3afc5SHans Verkuil 	}, {	// 5.7 MHz
290557a3afc5SHans Verkuil 		0x00010003, 0x00060001, 0xffecffc9, 0xffb4ffd4,
290657a3afc5SHans Verkuil 		0x004000d5, 0x013600f0, 0xffd3fe39, 0xfd04fd31,
290757a3afc5SHans Verkuil 		0xff360277, 0x055605ef, 0x033efdfe, 0xf8a5f642,
290857a3afc5SHans Verkuil 		0xf8cbffb6, 0x07e10cfb, 0x0bd50456, 0xf9dff1be,
290957a3afc5SHans Verkuil 		0xf067f6f2, 0x02520cd2, 0x110d0000,
291057a3afc5SHans Verkuil 	}, {	// 5.8 MHz
291157a3afc5SHans Verkuil 		0x00000003, 0x00080009, 0xfff8ffd2, 0xffaaffac,
291257a3afc5SHans Verkuil 		0x000200a3, 0x013c014a, 0x006dfec9, 0xfd2bfcb7,
291357a3afc5SHans Verkuil 		0xfe350165, 0x04cb0651, 0x0477ff7e, 0xf9a5f635,
291457a3afc5SHans Verkuil 		0xf7b1fe20, 0x069f0ca8, 0x0c81058b, 0xfaf0f231,
291557a3afc5SHans Verkuil 		0xf033f66d, 0x01e60cae, 0x110d0000,
291657a3afc5SHans Verkuil 	}, {	// 5.9 MHz
291757a3afc5SHans Verkuil 		0x00000002, 0x0009000e, 0x0005ffe1, 0xffacff90,
291857a3afc5SHans Verkuil 		0xffc5005f, 0x01210184, 0x00fcff72, 0xfd8afc77,
291957a3afc5SHans Verkuil 		0xfd51003f, 0x04020669, 0x05830103, 0xfad7f66b,
292057a3afc5SHans Verkuil 		0xf6c8fc93, 0x05430c2b, 0x0d0d06b5, 0xfc08f2b2,
292157a3afc5SHans Verkuil 		0xf00af5ec, 0x017b0c89, 0x110d0000,
292257a3afc5SHans Verkuil 	}, {	// 6.0 MHz
292357a3afc5SHans Verkuil 		0x00000001, 0x00070012, 0x0012fff5, 0xffbaff82,
292457a3afc5SHans Verkuil 		0xff8e000f, 0x00e80198, 0x01750028, 0xfe18fc75,
292557a3afc5SHans Verkuil 		0xfc99ff15, 0x03050636, 0x0656027f, 0xfc32f6e2,
292657a3afc5SHans Verkuil 		0xf614fb17, 0x03d20b87, 0x0d7707d2, 0xfd26f341,
292757a3afc5SHans Verkuil 		0xefeaf56f, 0x010f0c64, 0x110d0000,
292857a3afc5SHans Verkuil 	}, {	// 6.1 MHz
292957a3afc5SHans Verkuil 		0xffff0000, 0x00050012, 0x001c000b, 0xffd1ff84,
293057a3afc5SHans Verkuil 		0xff66ffbe, 0x00960184, 0x01cd00da, 0xfeccfcb2,
293157a3afc5SHans Verkuil 		0xfc17fdf9, 0x01e005bc, 0x06e703e4, 0xfdabf798,
293257a3afc5SHans Verkuil 		0xf599f9b3, 0x02510abd, 0x0dbf08df, 0xfe48f3dc,
293357a3afc5SHans Verkuil 		0xefd5f4f6, 0x00a20c3e, 0x110d0000,
293457a3afc5SHans Verkuil 	}, {	// 6.2 MHz
293557a3afc5SHans Verkuil 		0xfffffffe, 0x0002000f, 0x0021001f, 0xfff0ff97,
293657a3afc5SHans Verkuil 		0xff50ff74, 0x0034014a, 0x01fa0179, 0xff97fd2a,
293757a3afc5SHans Verkuil 		0xfbd3fcfa, 0x00a304fe, 0x07310525, 0xff37f886,
293857a3afc5SHans Verkuil 		0xf55cf86e, 0x00c709d0, 0x0de209db, 0xff6df484,
293957a3afc5SHans Verkuil 		0xefcbf481, 0x00360c18, 0x110d0000,
294057a3afc5SHans Verkuil 	}, {	// 6.3 MHz
294157a3afc5SHans Verkuil 		0xfffffffd, 0xfffe000a, 0x0021002f, 0x0010ffb8,
294257a3afc5SHans Verkuil 		0xff50ff3b, 0xffcc00f0, 0x01fa01fa, 0x0069fdd4,
294357a3afc5SHans Verkuil 		0xfbd3fc26, 0xff5d0407, 0x07310638, 0x00c9f9a8,
294457a3afc5SHans Verkuil 		0xf55cf74e, 0xff3908c3, 0x0de20ac3, 0x0093f537,
294557a3afc5SHans Verkuil 		0xefcbf410, 0xffca0bf2, 0x110d0000,
294657a3afc5SHans Verkuil 	}, {	// 6.4 MHz
294757a3afc5SHans Verkuil 		0xfffffffd, 0xfffb0003, 0x001c0037, 0x002fffe2,
294857a3afc5SHans Verkuil 		0xff66ff17, 0xff6a007e, 0x01cd0251, 0x0134fea5,
294957a3afc5SHans Verkuil 		0xfc17fb8b, 0xfe2002e0, 0x06e70713, 0x0255faf5,
295057a3afc5SHans Verkuil 		0xf599f658, 0xfdaf0799, 0x0dbf0b96, 0x01b8f5f5,
295157a3afc5SHans Verkuil 		0xefd5f3a3, 0xff5e0bca, 0x110d0000,
295257a3afc5SHans Verkuil 	}, {	// 6.5 MHz
295357a3afc5SHans Verkuil 		0x0000fffd, 0xfff9fffb, 0x00120037, 0x00460010,
295457a3afc5SHans Verkuil 		0xff8eff0f, 0xff180000, 0x01750276, 0x01e8ff8d,
295557a3afc5SHans Verkuil 		0xfc99fb31, 0xfcfb0198, 0x065607ad, 0x03cefc64,
295657a3afc5SHans Verkuil 		0xf614f592, 0xfc2e0656, 0x0d770c52, 0x02daf6bd,
295757a3afc5SHans Verkuil 		0xefeaf33b, 0xfef10ba3, 0x110d0000,
295857a3afc5SHans Verkuil 	}, {	// 6.6 MHz
295957a3afc5SHans Verkuil 		0x0000fffe, 0xfff7fff5, 0x0005002f, 0x0054003c,
296057a3afc5SHans Verkuil 		0xffc5ff22, 0xfedfff82, 0x00fc0267, 0x0276007e,
296157a3afc5SHans Verkuil 		0xfd51fb1c, 0xfbfe003e, 0x05830802, 0x0529fdec,
296257a3afc5SHans Verkuil 		0xf6c8f4fe, 0xfabd04ff, 0x0d0d0cf6, 0x03f8f78f,
296357a3afc5SHans Verkuil 		0xf00af2d7, 0xfe850b7b, 0x110d0000,
296457a3afc5SHans Verkuil 	}, {	// 6.7 MHz
296557a3afc5SHans Verkuil 		0x0000ffff, 0xfff8fff0, 0xfff80020, 0x00560060,
296657a3afc5SHans Verkuil 		0x0002ff4e, 0xfec4ff10, 0x006d0225, 0x02d50166,
296757a3afc5SHans Verkuil 		0xfe35fb4e, 0xfb35fee1, 0x0477080e, 0x065bff82,
296857a3afc5SHans Verkuil 		0xf7b1f4a0, 0xf9610397, 0x0c810d80, 0x0510f869,
296957a3afc5SHans Verkuil 		0xf033f278, 0xfe1a0b52, 0x110d0000,
297057a3afc5SHans Verkuil 	}, {	// 6.8 MHz
297157a3afc5SHans Verkuil 		0x00010000, 0xfffaffee, 0xffec000c, 0x004c0078,
297257a3afc5SHans Verkuil 		0x0040ff8e, 0xfecafeb6, 0xffd301b6, 0x02fc0235,
297357a3afc5SHans Verkuil 		0xff36fbc5, 0xfaaafd90, 0x033e07d2, 0x075b011b,
297457a3afc5SHans Verkuil 		0xf8cbf47a, 0xf81f0224, 0x0bd50def, 0x0621f94b,
297557a3afc5SHans Verkuil 		0xf067f21e, 0xfdae0b29, 0x110d0000,
297657a3afc5SHans Verkuil 	}, {	// 6.9 MHz
297757a3afc5SHans Verkuil 		0x00010001, 0xfffdffef, 0xffe3fff6, 0x0037007f,
297857a3afc5SHans Verkuil 		0x0075ffdc, 0xfef2fe7c, 0xff3d0122, 0x02ea02dd,
297957a3afc5SHans Verkuil 		0x0044fc79, 0xfa65fc5d, 0x01e3074e, 0x082102ad,
298057a3afc5SHans Verkuil 		0xfa0ff48c, 0xf6fe00a9, 0x0b0a0e43, 0x0729fa33,
298157a3afc5SHans Verkuil 		0xf0a5f1c9, 0xfd430b00, 0x110d0000,
298257a3afc5SHans Verkuil 	}, {	// 7.0 MHz
298357a3afc5SHans Verkuil 		0x00010002, 0x0001fff3, 0xffdeffe2, 0x001b0076,
298457a3afc5SHans Verkuil 		0x009c002d, 0xff35fe68, 0xfeba0076, 0x029f0352,
298557a3afc5SHans Verkuil 		0x014dfd60, 0xfa69fb53, 0x00740688, 0x08a7042d,
298657a3afc5SHans Verkuil 		0xfb75f4d6, 0xf600ff2d, 0x0a220e7a, 0x0827fb22,
298757a3afc5SHans Verkuil 		0xf0edf17a, 0xfcd80ad6, 0x110d0000,
298857a3afc5SHans Verkuil 	}, {	// 7.1 MHz
298957a3afc5SHans Verkuil 		0x00000003, 0x0004fff9, 0xffe0ffd2, 0xfffb005e,
299057a3afc5SHans Verkuil 		0x00b0007a, 0xff8ffe7c, 0xfe53ffc1, 0x0221038c,
299157a3afc5SHans Verkuil 		0x0241fe6e, 0xfab6fa80, 0xff010587, 0x08e90590,
299257a3afc5SHans Verkuil 		0xfcf5f556, 0xf52bfdb3, 0x09210e95, 0x0919fc15,
299357a3afc5SHans Verkuil 		0xf13ff12f, 0xfc6e0aab, 0x110d0000,
299457a3afc5SHans Verkuil 	}, {	// 7.2 MHz
299557a3afc5SHans Verkuil 		0x00000003, 0x00070000, 0xffe6ffc9, 0xffdb0039,
299657a3afc5SHans Verkuil 		0x00af00b8, 0xfff4feb6, 0xfe13ff10, 0x01790388,
299757a3afc5SHans Verkuil 		0x0311ff92, 0xfb48f9ed, 0xfd980453, 0x08e306cd,
299857a3afc5SHans Verkuil 		0xfe88f60a, 0xf482fc40, 0x08080e93, 0x09fdfd0c,
299957a3afc5SHans Verkuil 		0xf19af0ea, 0xfc050a81, 0x110d0000,
300057a3afc5SHans Verkuil 	}, {	// 7.3 MHz
300157a3afc5SHans Verkuil 		0x00000002, 0x00080008, 0xfff0ffc9, 0xffc1000d,
300257a3afc5SHans Verkuil 		0x009800e2, 0x005bff10, 0xfe00fe74, 0x00b50345,
300357a3afc5SHans Verkuil 		0x03b000bc, 0xfc18f9a1, 0xfc4802f9, 0x089807dc,
300457a3afc5SHans Verkuil 		0x0022f6f0, 0xf407fada, 0x06da0e74, 0x0ad3fe06,
300557a3afc5SHans Verkuil 		0xf1fef0ab, 0xfb9c0a55, 0x110d0000,
300657a3afc5SHans Verkuil 	}, {	// 7.4 MHz
300757a3afc5SHans Verkuil 		0x00000001, 0x0008000e, 0xfffdffd0, 0xffafffdf,
300857a3afc5SHans Verkuil 		0x006e00f2, 0x00b8ff82, 0xfe1bfdf8, 0xffe302c8,
300957a3afc5SHans Verkuil 		0x041301dc, 0xfd1af99e, 0xfb1e0183, 0x080908b5,
301057a3afc5SHans Verkuil 		0x01bcf801, 0xf3bdf985, 0x059a0e38, 0x0b99ff03,
301157a3afc5SHans Verkuil 		0xf26cf071, 0xfb330a2a, 0x110d0000,
301257a3afc5SHans Verkuil 	}, {	// 7.5 MHz
301357a3afc5SHans Verkuil 		0xffff0000, 0x00070011, 0x000affdf, 0xffa9ffb5,
301457a3afc5SHans Verkuil 		0x003700e6, 0x01010000, 0xfe62fda8, 0xff140219,
301557a3afc5SHans Verkuil 		0x043502e1, 0xfe42f9e6, 0xfa270000, 0x073a0953,
301657a3afc5SHans Verkuil 		0x034cf939, 0xf3a4f845, 0x044c0de1, 0x0c4f0000,
301757a3afc5SHans Verkuil 		0xf2e2f03c, 0xfacc09fe, 0x110d0000,
301857a3afc5SHans Verkuil 	}, {	// 7.6 MHz
301957a3afc5SHans Verkuil 		0xffffffff, 0x00040012, 0x0016fff3, 0xffafff95,
302057a3afc5SHans Verkuil 		0xfff900c0, 0x0130007e, 0xfecefd89, 0xfe560146,
302157a3afc5SHans Verkuil 		0x041303bc, 0xff81fa76, 0xf96cfe7d, 0x063209b1,
302257a3afc5SHans Verkuil 		0x04c9fa93, 0xf3bdf71e, 0x02f30d6e, 0x0cf200fd,
302357a3afc5SHans Verkuil 		0xf361f00e, 0xfa6509d1, 0x110d0000,
302457a3afc5SHans Verkuil 	}, {	// 7.7 MHz
302557a3afc5SHans Verkuil 		0xfffffffe, 0x00010010, 0x001e0008, 0xffc1ff84,
302657a3afc5SHans Verkuil 		0xffbc0084, 0x013e00f0, 0xff56fd9f, 0xfdb8005c,
302757a3afc5SHans Verkuil 		0x03b00460, 0x00c7fb45, 0xf8f4fd07, 0x04fa09ce,
302857a3afc5SHans Verkuil 		0x062afc07, 0xf407f614, 0x01920ce0, 0x0d8301fa,
302957a3afc5SHans Verkuil 		0xf3e8efe5, 0xfa0009a4, 0x110d0000,
303057a3afc5SHans Verkuil 	}, {	// 7.8 MHz
303157a3afc5SHans Verkuil 		0x0000fffd, 0xfffd000b, 0x0022001d, 0xffdbff82,
303257a3afc5SHans Verkuil 		0xff870039, 0x012a014a, 0xffedfde7, 0xfd47ff6b,
303357a3afc5SHans Verkuil 		0x031104c6, 0x0202fc4c, 0xf8c6fbad, 0x039909a7,
303457a3afc5SHans Verkuil 		0x0767fd8e, 0xf482f52b, 0x002d0c39, 0x0e0002f4,
303557a3afc5SHans Verkuil 		0xf477efc2, 0xf99b0977, 0x110d0000,
303657a3afc5SHans Verkuil 	}, {	// 7.9 MHz
303757a3afc5SHans Verkuil 		0x0000fffd, 0xfffa0004, 0x0020002d, 0xfffbff91,
303857a3afc5SHans Verkuil 		0xff61ffe8, 0x00f70184, 0x0086fe5c, 0xfd0bfe85,
303957a3afc5SHans Verkuil 		0x024104e5, 0x0323fd7d, 0xf8e2fa79, 0x021d093f,
304057a3afc5SHans Verkuil 		0x0879ff22, 0xf52bf465, 0xfec70b79, 0x0e6803eb,
304157a3afc5SHans Verkuil 		0xf50defa5, 0xf937094a, 0x110d0000,
304257a3afc5SHans Verkuil 	}, {	// 8.0 MHz
304357a3afc5SHans Verkuil 		0x0000fffe, 0xfff8fffd, 0x00190036, 0x001bffaf,
304457a3afc5SHans Verkuil 		0xff4fff99, 0x00aa0198, 0x0112fef3, 0xfd09fdb9,
304557a3afc5SHans Verkuil 		0x014d04be, 0x041bfecc, 0xf947f978, 0x00900897,
304657a3afc5SHans Verkuil 		0x095a00b9, 0xf600f3c5, 0xfd650aa3, 0x0ebc04de,
304757a3afc5SHans Verkuil 		0xf5aaef8e, 0xf8d5091c, 0x110d0000,
304857a3afc5SHans Verkuil 	}, {	// 8.1 MHz
304957a3afc5SHans Verkuil 		0x0000ffff, 0xfff7fff6, 0x000e0038, 0x0037ffd7,
305057a3afc5SHans Verkuil 		0xff52ff56, 0x004b0184, 0x0186ffa1, 0xfd40fd16,
305157a3afc5SHans Verkuil 		0x00440452, 0x04de0029, 0xf9f2f8b2, 0xfefe07b5,
305257a3afc5SHans Verkuil 		0x0a05024d, 0xf6fef34d, 0xfc0a09b8, 0x0efa05cd,
305357a3afc5SHans Verkuil 		0xf64eef7d, 0xf87308ed, 0x110d0000,
305457a3afc5SHans Verkuil 	}, {	// 8.2 MHz
305557a3afc5SHans Verkuil 		0x00010000, 0xfff8fff0, 0x00000031, 0x004c0005,
305657a3afc5SHans Verkuil 		0xff6aff27, 0xffe4014a, 0x01d70057, 0xfdacfca6,
305757a3afc5SHans Verkuil 		0xff3603a7, 0x05610184, 0xfadbf82e, 0xfd74069f,
305857a3afc5SHans Verkuil 		0x0a7503d6, 0xf81ff2ff, 0xfab808b9, 0x0f2306b5,
305957a3afc5SHans Verkuil 		0xf6f9ef72, 0xf81308bf, 0x110d0000,
306057a3afc5SHans Verkuil 	}, {	// 8.3 MHz
306157a3afc5SHans Verkuil 		0x00010001, 0xfffbffee, 0xfff30022, 0x00560032,
306257a3afc5SHans Verkuil 		0xff95ff10, 0xff8000f0, 0x01fe0106, 0xfe46fc71,
306357a3afc5SHans Verkuil 		0xfe3502c7, 0x059e02ce, 0xfbf9f7f2, 0xfbff055b,
306457a3afc5SHans Verkuil 		0x0aa9054c, 0xf961f2db, 0xf97507aa, 0x0f350797,
306557a3afc5SHans Verkuil 		0xf7a9ef6d, 0xf7b40890, 0x110d0000,
306657a3afc5SHans Verkuil 	}, {	// 8.4 MHz
306757a3afc5SHans Verkuil 		0x00010002, 0xfffeffee, 0xffe8000f, 0x00540058,
306857a3afc5SHans Verkuil 		0xffcdff14, 0xff29007e, 0x01f6019e, 0xff01fc7c,
306957a3afc5SHans Verkuil 		0xfd5101bf, 0x059203f6, 0xfd41f7fe, 0xfaa903f3,
307057a3afc5SHans Verkuil 		0x0a9e06a9, 0xfabdf2e2, 0xf842068b, 0x0f320871,
307157a3afc5SHans Verkuil 		0xf85eef6e, 0xf7560860, 0x110d0000,
307257a3afc5SHans Verkuil 	}, {	// 8.5 MHz
307357a3afc5SHans Verkuil 		0x00000003, 0x0002fff2, 0xffe1fff9, 0x00460073,
307457a3afc5SHans Verkuil 		0x000bff34, 0xfee90000, 0x01c10215, 0xffd0fcc5,
307557a3afc5SHans Verkuil 		0xfc99009d, 0x053d04f1, 0xfea5f853, 0xf97d0270,
307657a3afc5SHans Verkuil 		0x0a5607e4, 0xfc2ef314, 0xf723055f, 0x0f180943,
307757a3afc5SHans Verkuil 		0xf919ef75, 0xf6fa0830, 0x110d0000,
307857a3afc5SHans Verkuil 	}, {	// 8.6 MHz
307957a3afc5SHans Verkuil 		0x00000003, 0x0005fff8, 0xffdeffe4, 0x002f007f,
308057a3afc5SHans Verkuil 		0x0048ff6b, 0xfec7ff82, 0x0163025f, 0x00a2fd47,
308157a3afc5SHans Verkuil 		0xfc17ff73, 0x04a405b2, 0x0017f8ed, 0xf88500dc,
308257a3afc5SHans Verkuil 		0x09d208f9, 0xfdaff370, 0xf61c0429, 0x0ee80a0b,
308357a3afc5SHans Verkuil 		0xf9d8ef82, 0xf6a00800, 0x110d0000,
308457a3afc5SHans Verkuil 	}, {	// 8.7 MHz
308557a3afc5SHans Verkuil 		0x00000003, 0x0007ffff, 0xffe1ffd4, 0x0010007a,
308657a3afc5SHans Verkuil 		0x007cffb2, 0xfec6ff10, 0x00e60277, 0x0168fdf9,
308757a3afc5SHans Verkuil 		0xfbd3fe50, 0x03ce0631, 0x0188f9c8, 0xf7c7ff43,
308857a3afc5SHans Verkuil 		0x091509e3, 0xff39f3f6, 0xf52d02ea, 0x0ea30ac9,
308957a3afc5SHans Verkuil 		0xfa9bef95, 0xf64607d0, 0x110d0000,
309057a3afc5SHans Verkuil 	}, {	// 8.8 MHz
309157a3afc5SHans Verkuil 		0x00000002, 0x00090007, 0xffe9ffca, 0xfff00065,
309257a3afc5SHans Verkuil 		0x00a10003, 0xfee6feb6, 0x0053025b, 0x0213fed0,
309357a3afc5SHans Verkuil 		0xfbd3fd46, 0x02c70668, 0x02eafadb, 0xf74bfdae,
309457a3afc5SHans Verkuil 		0x08230a9c, 0x00c7f4a3, 0xf45b01a6, 0x0e480b7c,
309557a3afc5SHans Verkuil 		0xfb61efae, 0xf5ef079f, 0x110d0000,
309657a3afc5SHans Verkuil 	}, {	// 8.9 MHz
309757a3afc5SHans Verkuil 		0xffff0000, 0x0008000d, 0xfff5ffc8, 0xffd10043,
309857a3afc5SHans Verkuil 		0x00b20053, 0xff24fe7c, 0xffb9020c, 0x0295ffbb,
309957a3afc5SHans Verkuil 		0xfc17fc64, 0x019b0654, 0x042dfc1c, 0xf714fc2a,
310057a3afc5SHans Verkuil 		0x07020b21, 0x0251f575, 0xf3a7005e, 0x0dd80c24,
310157a3afc5SHans Verkuil 		0xfc2aefcd, 0xf599076e, 0x110d0000,
310257a3afc5SHans Verkuil 	}, {	// 9.0 MHz
310357a3afc5SHans Verkuil 		0xffffffff, 0x00060011, 0x0002ffcf, 0xffba0018,
310457a3afc5SHans Verkuil 		0x00ad009a, 0xff79fe68, 0xff260192, 0x02e500ab,
310557a3afc5SHans Verkuil 		0xfc99fbb6, 0x005b05f7, 0x0545fd81, 0xf723fabf,
310657a3afc5SHans Verkuil 		0x05b80b70, 0x03d2f669, 0xf313ff15, 0x0d550cbf,
310757a3afc5SHans Verkuil 		0xfcf6eff2, 0xf544073d, 0x110d0000,
310857a3afc5SHans Verkuil 	}, {	// 9.1 MHz
310957a3afc5SHans Verkuil 		0xfffffffe, 0x00030012, 0x000fffdd, 0xffacffea,
311057a3afc5SHans Verkuil 		0x009300cf, 0xffdcfe7c, 0xfea600f7, 0x02fd0190,
311157a3afc5SHans Verkuil 		0xfd51fb46, 0xff150554, 0x0627fefd, 0xf778f978,
311257a3afc5SHans Verkuil 		0x044d0b87, 0x0543f77d, 0xf2a0fdcf, 0x0cbe0d4e,
311357a3afc5SHans Verkuil 		0xfdc4f01d, 0xf4f2070b, 0x110d0000,
311457a3afc5SHans Verkuil 	}, {	// 9.2 MHz
311557a3afc5SHans Verkuil 		0x0000fffd, 0x00000010, 0x001afff0, 0xffaaffbf,
311657a3afc5SHans Verkuil 		0x006700ed, 0x0043feb6, 0xfe460047, 0x02db0258,
311757a3afc5SHans Verkuil 		0xfe35fb1b, 0xfddc0473, 0x06c90082, 0xf811f85e,
311857a3afc5SHans Verkuil 		0x02c90b66, 0x069ff8ad, 0xf250fc8d, 0x0c140dcf,
311957a3afc5SHans Verkuil 		0xfe93f04d, 0xf4a106d9, 0x110d0000,
312057a3afc5SHans Verkuil 	}, {	// 9.3 MHz
312157a3afc5SHans Verkuil 		0x0000fffd, 0xfffc000c, 0x00200006, 0xffb4ff9c,
312257a3afc5SHans Verkuil 		0x002f00ef, 0x00a4ff10, 0xfe0dff92, 0x028102f7,
312357a3afc5SHans Verkuil 		0xff36fb37, 0xfcbf035e, 0x07260202, 0xf8e8f778,
312457a3afc5SHans Verkuil 		0x01340b0d, 0x07e1f9f4, 0xf223fb51, 0x0b590e42,
312557a3afc5SHans Verkuil 		0xff64f083, 0xf45206a7, 0x110d0000,
312657a3afc5SHans Verkuil 	}, {	// 9.4 MHz
312757a3afc5SHans Verkuil 		0x0000fffd, 0xfff90005, 0x0022001a, 0xffc9ff86,
312857a3afc5SHans Verkuil 		0xfff000d7, 0x00f2ff82, 0xfe01fee5, 0x01f60362,
312957a3afc5SHans Verkuil 		0x0044fb99, 0xfbcc0222, 0x07380370, 0xf9f7f6cc,
313057a3afc5SHans Verkuil 		0xff990a7e, 0x0902fb50, 0xf21afa1f, 0x0a8d0ea6,
313157a3afc5SHans Verkuil 		0x0034f0bf, 0xf4050675, 0x110d0000,
313257a3afc5SHans Verkuil 	}, {	// 9.5 MHz
313357a3afc5SHans Verkuil 		0x0000fffe, 0xfff8fffe, 0x001e002b, 0xffe5ff81,
313457a3afc5SHans Verkuil 		0xffb400a5, 0x01280000, 0xfe24fe50, 0x01460390,
313557a3afc5SHans Verkuil 		0x014dfc3a, 0xfb1000ce, 0x070104bf, 0xfb37f65f,
313657a3afc5SHans Verkuil 		0xfe0009bc, 0x0a00fcbb, 0xf235f8f8, 0x09b20efc,
313757a3afc5SHans Verkuil 		0x0105f101, 0xf3ba0642, 0x110d0000,
313857a3afc5SHans Verkuil 	}, {	// 9.6 MHz
313957a3afc5SHans Verkuil 		0x0001ffff, 0xfff8fff7, 0x00150036, 0x0005ff8c,
314057a3afc5SHans Verkuil 		0xff810061, 0x013d007e, 0xfe71fddf, 0x007c0380,
314157a3afc5SHans Verkuil 		0x0241fd13, 0xfa94ff70, 0x068005e2, 0xfc9bf633,
314257a3afc5SHans Verkuil 		0xfc7308ca, 0x0ad5fe30, 0xf274f7e0, 0x08c90f43,
314357a3afc5SHans Verkuil 		0x01d4f147, 0xf371060f, 0x110d0000,
314457a3afc5SHans Verkuil 	}, {	// 9.7 MHz
314557a3afc5SHans Verkuil 		0x00010001, 0xfff9fff1, 0x00090038, 0x0025ffa7,
314657a3afc5SHans Verkuil 		0xff5e0012, 0x013200f0, 0xfee3fd9b, 0xffaa0331,
314757a3afc5SHans Verkuil 		0x0311fe15, 0xfa60fe18, 0x05bd06d1, 0xfe1bf64a,
314857a3afc5SHans Verkuil 		0xfafa07ae, 0x0b7effab, 0xf2d5f6d7, 0x07d30f7a,
314957a3afc5SHans Verkuil 		0x02a3f194, 0xf32905dc, 0x110d0000,
315057a3afc5SHans Verkuil 	}, {	// 9.8 MHz
315157a3afc5SHans Verkuil 		0x00010002, 0xfffcffee, 0xfffb0032, 0x003fffcd,
315257a3afc5SHans Verkuil 		0xff4effc1, 0x0106014a, 0xff6efd8a, 0xfedd02aa,
315357a3afc5SHans Verkuil 		0x03b0ff34, 0xfa74fcd7, 0x04bf0781, 0xffaaf6a3,
315457a3afc5SHans Verkuil 		0xf99e066b, 0x0bf90128, 0xf359f5e1, 0x06d20fa2,
315557a3afc5SHans Verkuil 		0x0370f1e5, 0xf2e405a8, 0x110d0000,
315657a3afc5SHans Verkuil 	}, {	// 9.9 MHz
315757a3afc5SHans Verkuil 		0x00000003, 0xffffffee, 0xffef0024, 0x0051fffa,
315857a3afc5SHans Verkuil 		0xff54ff77, 0x00be0184, 0x0006fdad, 0xfe2701f3,
315957a3afc5SHans Verkuil 		0x0413005e, 0xfad1fbba, 0x039007ee, 0x013bf73d,
316057a3afc5SHans Verkuil 		0xf868050a, 0x0c4302a1, 0xf3fdf4fe, 0x05c70fba,
316157a3afc5SHans Verkuil 		0x043bf23c, 0xf2a10575, 0x110d0000,
316257a3afc5SHans Verkuil 	}, {	// 10.0 MHz
316357a3afc5SHans Verkuil 		0x00000003, 0x0003fff1, 0xffe50011, 0x00570027,
316457a3afc5SHans Verkuil 		0xff70ff3c, 0x00620198, 0x009efe01, 0xfd95011a,
316557a3afc5SHans Verkuil 		0x04350183, 0xfb71fad0, 0x023c0812, 0x02c3f811,
316657a3afc5SHans Verkuil 		0xf75e0390, 0x0c5c0411, 0xf4c1f432, 0x04b30fc1,
316757a3afc5SHans Verkuil 		0x0503f297, 0xf2610541, 0x110d0000,
316857a3afc5SHans Verkuil 	}, {	// 10.1 MHz
316957a3afc5SHans Verkuil 		0x00000003, 0x0006fff7, 0xffdffffc, 0x00510050,
317057a3afc5SHans Verkuil 		0xff9dff18, 0xfffc0184, 0x0128fe80, 0xfd32002e,
317157a3afc5SHans Verkuil 		0x04130292, 0xfc4dfa21, 0x00d107ee, 0x0435f91c,
317257a3afc5SHans Verkuil 		0xf6850205, 0x0c430573, 0xf5a1f37d, 0x03990fba,
317357a3afc5SHans Verkuil 		0x05c7f2f8, 0xf222050d, 0x110d0000,
317457a3afc5SHans Verkuil 	}, {	// 10.2 MHz
317557a3afc5SHans Verkuil 		0x00000002, 0x0008fffe, 0xffdfffe7, 0x003f006e,
317657a3afc5SHans Verkuil 		0xffd6ff0f, 0xff96014a, 0x0197ff1f, 0xfd05ff3e,
317757a3afc5SHans Verkuil 		0x03b0037c, 0xfd59f9b7, 0xff5d0781, 0x0585fa56,
317857a3afc5SHans Verkuil 		0xf5e4006f, 0x0bf906c4, 0xf69df2e0, 0x02790fa2,
317957a3afc5SHans Verkuil 		0x0688f35d, 0xf1e604d8, 0x110d0000,
318057a3afc5SHans Verkuil 	}, {	// 10.3 MHz
318157a3afc5SHans Verkuil 		0xffff0001, 0x00090005, 0xffe4ffd6, 0x0025007e,
318257a3afc5SHans Verkuil 		0x0014ff20, 0xff3c00f0, 0x01e1ffd0, 0xfd12fe5c,
318357a3afc5SHans Verkuil 		0x03110433, 0xfe88f996, 0xfdf106d1, 0x06aafbb7,
318457a3afc5SHans Verkuil 		0xf57efed8, 0x0b7e07ff, 0xf7b0f25e, 0x01560f7a,
318557a3afc5SHans Verkuil 		0x0745f3c7, 0xf1ac04a4, 0x110d0000,
318657a3afc5SHans Verkuil 	}, {	// 10.4 MHz
318757a3afc5SHans Verkuil 		0xffffffff, 0x0008000c, 0xffedffcb, 0x0005007d,
318857a3afc5SHans Verkuil 		0x0050ff4c, 0xfef6007e, 0x01ff0086, 0xfd58fd97,
318957a3afc5SHans Verkuil 		0x024104ad, 0xffcaf9c0, 0xfc9905e2, 0x079afd35,
319057a3afc5SHans Verkuil 		0xf555fd46, 0x0ad50920, 0xf8d9f1f6, 0x00310f43,
319157a3afc5SHans Verkuil 		0x07fdf435, 0xf174046f, 0x110d0000,
319257a3afc5SHans Verkuil 	}, {	// 10.5 MHz
319357a3afc5SHans Verkuil 		0xfffffffe, 0x00050011, 0xfffaffc8, 0xffe5006b,
319457a3afc5SHans Verkuil 		0x0082ff8c, 0xfecc0000, 0x01f00130, 0xfdd2fcfc,
319557a3afc5SHans Verkuil 		0x014d04e3, 0x010efa32, 0xfb6404bf, 0x084efec5,
319657a3afc5SHans Verkuil 		0xf569fbc2, 0x0a000a23, 0xfa15f1ab, 0xff0b0efc,
319757a3afc5SHans Verkuil 		0x08b0f4a7, 0xf13f043a, 0x110d0000,
319857a3afc5SHans Verkuil 	}, {	// 10.6 MHz
319957a3afc5SHans Verkuil 		0x0000fffd, 0x00020012, 0x0007ffcd, 0xffc9004c,
320057a3afc5SHans Verkuil 		0x00a4ffd9, 0xfec3ff82, 0x01b401c1, 0xfe76fc97,
320157a3afc5SHans Verkuil 		0x004404d2, 0x0245fae8, 0xfa5f0370, 0x08c1005f,
320257a3afc5SHans Verkuil 		0xf5bcfa52, 0x09020b04, 0xfb60f17b, 0xfde70ea6,
320357a3afc5SHans Verkuil 		0x095df51e, 0xf10c0405, 0x110d0000,
320457a3afc5SHans Verkuil 	}, {	// 10.7 MHz
320557a3afc5SHans Verkuil 		0x0000fffd, 0xffff0011, 0x0014ffdb, 0xffb40023,
320657a3afc5SHans Verkuil 		0x00b2002a, 0xfedbff10, 0x0150022d, 0xff38fc6f,
320757a3afc5SHans Verkuil 		0xff36047b, 0x035efbda, 0xf9940202, 0x08ee01f5,
320857a3afc5SHans Verkuil 		0xf649f8fe, 0x07e10bc2, 0xfcb6f169, 0xfcc60e42,
320957a3afc5SHans Verkuil 		0x0a04f599, 0xf0db03d0, 0x110d0000,
321057a3afc5SHans Verkuil 	}, {	// 10.8 MHz
321157a3afc5SHans Verkuil 		0x0000fffd, 0xfffb000d, 0x001dffed, 0xffaafff5,
321257a3afc5SHans Verkuil 		0x00aa0077, 0xff13feb6, 0x00ce026b, 0x000afc85,
321357a3afc5SHans Verkuil 		0xfe3503e3, 0x044cfcfb, 0xf90c0082, 0x08d5037f,
321457a3afc5SHans Verkuil 		0xf710f7cc, 0x069f0c59, 0xfe16f173, 0xfbaa0dcf,
321557a3afc5SHans Verkuil 		0x0aa5f617, 0xf0ad039b, 0x110d0000,
321657a3afc5SHans Verkuil 	}, {	// 10.9 MHz
321757a3afc5SHans Verkuil 		0x0000fffe, 0xfff90006, 0x00210003, 0xffacffc8,
321857a3afc5SHans Verkuil 		0x008e00b6, 0xff63fe7c, 0x003a0275, 0x00dafcda,
321957a3afc5SHans Verkuil 		0xfd510313, 0x0501fe40, 0xf8cbfefd, 0x087604f0,
322057a3afc5SHans Verkuil 		0xf80af6c2, 0x05430cc8, 0xff7af19a, 0xfa940d4e,
322157a3afc5SHans Verkuil 		0x0b3ff699, 0xf0810365, 0x110d0000,
322257a3afc5SHans Verkuil 	}, {	// 11.0 MHz
322357a3afc5SHans Verkuil 		0x0001ffff, 0xfff8ffff, 0x00210018, 0xffbaffa3,
322457a3afc5SHans Verkuil 		0x006000e1, 0xffc4fe68, 0xffa0024b, 0x019afd66,
322557a3afc5SHans Verkuil 		0xfc990216, 0x0575ff99, 0xf8d4fd81, 0x07d40640,
322657a3afc5SHans Verkuil 		0xf932f5e6, 0x03d20d0d, 0x00dff1de, 0xf9860cbf,
322757a3afc5SHans Verkuil 		0x0bd1f71e, 0xf058032f, 0x110d0000,
322857a3afc5SHans Verkuil 	}, {	// 11.1 MHz
322957a3afc5SHans Verkuil 		0x00010000, 0xfff8fff8, 0x001b0029, 0xffd1ff8a,
323057a3afc5SHans Verkuil 		0x002600f2, 0x002cfe7c, 0xff0f01f0, 0x023bfe20,
323157a3afc5SHans Verkuil 		0xfc1700fa, 0x05a200f7, 0xf927fc1c, 0x06f40765,
323257a3afc5SHans Verkuil 		0xfa82f53b, 0x02510d27, 0x0243f23d, 0xf8810c24,
323357a3afc5SHans Verkuil 		0x0c5cf7a7, 0xf03102fa, 0x110d0000,
323457a3afc5SHans Verkuil 	}, {	// 11.2 MHz
323557a3afc5SHans Verkuil 		0x00010002, 0xfffafff2, 0x00110035, 0xfff0ff81,
323657a3afc5SHans Verkuil 		0xffe700e7, 0x008ffeb6, 0xfe94016d, 0x02b0fefb,
323757a3afc5SHans Verkuil 		0xfbd3ffd1, 0x05850249, 0xf9c1fadb, 0x05de0858,
323857a3afc5SHans Verkuil 		0xfbf2f4c4, 0x00c70d17, 0x03a0f2b8, 0xf7870b7c,
323957a3afc5SHans Verkuil 		0x0cdff833, 0xf00d02c4, 0x110d0000,
324057a3afc5SHans Verkuil 	}, {	// 11.3 MHz
324157a3afc5SHans Verkuil 		0x00000003, 0xfffdffee, 0x00040038, 0x0010ff88,
324257a3afc5SHans Verkuil 		0xffac00c2, 0x00e2ff10, 0xfe3900cb, 0x02f1ffe9,
324357a3afc5SHans Verkuil 		0xfbd3feaa, 0x05210381, 0xfa9cf9c8, 0x04990912,
324457a3afc5SHans Verkuil 		0xfd7af484, 0xff390cdb, 0x04f4f34d, 0xf69a0ac9,
324557a3afc5SHans Verkuil 		0x0d5af8c1, 0xefec028e, 0x110d0000,
324657a3afc5SHans Verkuil 	}, {	// 11.4 MHz
324757a3afc5SHans Verkuil 		0x00000003, 0x0000ffee, 0xfff60033, 0x002fff9f,
324857a3afc5SHans Verkuil 		0xff7b0087, 0x011eff82, 0xfe080018, 0x02f900d8,
324957a3afc5SHans Verkuil 		0xfc17fd96, 0x04790490, 0xfbadf8ed, 0x032f098e,
325057a3afc5SHans Verkuil 		0xff10f47d, 0xfdaf0c75, 0x063cf3fc, 0xf5ba0a0b,
325157a3afc5SHans Verkuil 		0x0dccf952, 0xefcd0258, 0x110d0000,
325257a3afc5SHans Verkuil 	}, {	// 11.5 MHz
325357a3afc5SHans Verkuil 		0x00000003, 0x0004fff1, 0xffea0026, 0x0046ffc3,
325457a3afc5SHans Verkuil 		0xff5a003c, 0x013b0000, 0xfe04ff63, 0x02c801b8,
325557a3afc5SHans Verkuil 		0xfc99fca6, 0x0397056a, 0xfcecf853, 0x01ad09c9,
325657a3afc5SHans Verkuil 		0x00acf4ad, 0xfc2e0be7, 0x0773f4c2, 0xf4e90943,
325757a3afc5SHans Verkuil 		0x0e35f9e6, 0xefb10221, 0x110d0000,
325857a3afc5SHans Verkuil 	}, {	// 11.6 MHz
325957a3afc5SHans Verkuil 		0x00000002, 0x0007fff6, 0xffe20014, 0x0054ffee,
326057a3afc5SHans Verkuil 		0xff4effeb, 0x0137007e, 0xfe2efebb, 0x0260027a,
326157a3afc5SHans Verkuil 		0xfd51fbe6, 0x02870605, 0xfe4af7fe, 0x001d09c1,
326257a3afc5SHans Verkuil 		0x0243f515, 0xfabd0b32, 0x0897f59e, 0xf4280871,
326357a3afc5SHans Verkuil 		0x0e95fa7c, 0xef9701eb, 0x110d0000,
326457a3afc5SHans Verkuil 	}, {	// 11.7 MHz
326557a3afc5SHans Verkuil 		0xffff0001, 0x0008fffd, 0xffdeffff, 0x0056001d,
326657a3afc5SHans Verkuil 		0xff57ff9c, 0x011300f0, 0xfe82fe2e, 0x01ca0310,
326757a3afc5SHans Verkuil 		0xfe35fb62, 0x0155065a, 0xffbaf7f2, 0xfe8c0977,
326857a3afc5SHans Verkuil 		0x03cef5b2, 0xf9610a58, 0x09a5f68f, 0xf3790797,
326957a3afc5SHans Verkuil 		0x0eebfb14, 0xef8001b5, 0x110d0000,
327057a3afc5SHans Verkuil 	}, {	// 11.8 MHz
327157a3afc5SHans Verkuil 		0xffff0000, 0x00080004, 0xffe0ffe9, 0x004c0047,
327257a3afc5SHans Verkuil 		0xff75ff58, 0x00d1014a, 0xfef9fdc8, 0x0111036f,
327357a3afc5SHans Verkuil 		0xff36fb21, 0x00120665, 0x012df82e, 0xfd0708ec,
327457a3afc5SHans Verkuil 		0x0542f682, 0xf81f095c, 0x0a9af792, 0xf2db06b5,
327557a3afc5SHans Verkuil 		0x0f38fbad, 0xef6c017e, 0x110d0000,
327657a3afc5SHans Verkuil 	}, {	// 11.9 MHz
327757a3afc5SHans Verkuil 		0xffffffff, 0x0007000b, 0xffe7ffd8, 0x00370068,
327857a3afc5SHans Verkuil 		0xffa4ff28, 0x00790184, 0xff87fd91, 0x00430392,
327957a3afc5SHans Verkuil 		0x0044fb26, 0xfece0626, 0x0294f8b2, 0xfb990825,
328057a3afc5SHans Verkuil 		0x0698f77f, 0xf6fe0842, 0x0b73f8a7, 0xf25105cd,
328157a3afc5SHans Verkuil 		0x0f7bfc48, 0xef5a0148, 0x110d0000,
328257a3afc5SHans Verkuil 	}, {	// 12.0 MHz
328357a3afc5SHans Verkuil 		0x0000fffe, 0x00050010, 0xfff2ffcc, 0x001b007b,
328457a3afc5SHans Verkuil 		0xffdfff10, 0x00140198, 0x0020fd8e, 0xff710375,
328557a3afc5SHans Verkuil 		0x014dfb73, 0xfd9a059f, 0x03e0f978, 0xfa4e0726,
328657a3afc5SHans Verkuil 		0x07c8f8a7, 0xf600070c, 0x0c2ff9c9, 0xf1db04de,
328757a3afc5SHans Verkuil 		0x0fb4fce5, 0xef4b0111, 0x110d0000,
328857a3afc5SHans Verkuil 	}, {	// 12.1 MHz
328957a3afc5SHans Verkuil 		0x0000fffd, 0x00010012, 0xffffffc8, 0xfffb007e,
329057a3afc5SHans Verkuil 		0x001dff14, 0xffad0184, 0x00b7fdbe, 0xfea9031b,
329157a3afc5SHans Verkuil 		0x0241fc01, 0xfc8504d6, 0x0504fa79, 0xf93005f6,
329257a3afc5SHans Verkuil 		0x08caf9f2, 0xf52b05c0, 0x0ccbfaf9, 0xf17903eb,
329357a3afc5SHans Verkuil 		0x0fe3fd83, 0xef3f00db, 0x110d0000,
329457a3afc5SHans Verkuil 	}, {	// 12.2 MHz
329557a3afc5SHans Verkuil 		0x0000fffd, 0xfffe0011, 0x000cffcc, 0xffdb0071,
329657a3afc5SHans Verkuil 		0x0058ff32, 0xff4f014a, 0x013cfe1f, 0xfdfb028a,
329757a3afc5SHans Verkuil 		0x0311fcc9, 0xfb9d03d6, 0x05f4fbad, 0xf848049d,
329857a3afc5SHans Verkuil 		0x0999fb5b, 0xf4820461, 0x0d46fc32, 0xf12d02f4,
329957a3afc5SHans Verkuil 		0x1007fe21, 0xef3600a4, 0x110d0000,
330057a3afc5SHans Verkuil 	}, {	// 12.3 MHz
330157a3afc5SHans Verkuil 		0x0000fffe, 0xfffa000e, 0x0017ffd9, 0xffc10055,
330257a3afc5SHans Verkuil 		0x0088ff68, 0xff0400f0, 0x01a6fea7, 0xfd7501cc,
330357a3afc5SHans Verkuil 		0x03b0fdc0, 0xfaef02a8, 0x06a7fd07, 0xf79d0326,
330457a3afc5SHans Verkuil 		0x0a31fcda, 0xf40702f3, 0x0d9ffd72, 0xf0f601fa,
330557a3afc5SHans Verkuil 		0x1021fec0, 0xef2f006d, 0x110d0000,
330657a3afc5SHans Verkuil 	}, {	// 12.4 MHz
330757a3afc5SHans Verkuil 		0x0001ffff, 0xfff80007, 0x001fffeb, 0xffaf002d,
330857a3afc5SHans Verkuil 		0x00a8ffb0, 0xfed3007e, 0x01e9ff4c, 0xfd2000ee,
330957a3afc5SHans Verkuil 		0x0413fed8, 0xfa82015c, 0x0715fe7d, 0xf7340198,
331057a3afc5SHans Verkuil 		0x0a8dfe69, 0xf3bd017c, 0x0dd5feb8, 0xf0d500fd,
331157a3afc5SHans Verkuil 		0x1031ff60, 0xef2b0037, 0x110d0000,
331257a3afc5SHans Verkuil 	}, {	// 12.5 MHz
331357a3afc5SHans Verkuil 		0x00010000, 0xfff70000, 0x00220000, 0xffa90000,
331457a3afc5SHans Verkuil 		0x00b30000, 0xfec20000, 0x02000000, 0xfd030000,
331557a3afc5SHans Verkuil 		0x04350000, 0xfa5e0000, 0x073b0000, 0xf7110000,
331657a3afc5SHans Verkuil 		0x0aac0000, 0xf3a40000, 0x0de70000, 0xf0c90000,
331757a3afc5SHans Verkuil 		0x10360000, 0xef290000, 0x110d0000,
331857a3afc5SHans Verkuil 	}, {	// 12.6 MHz
331957a3afc5SHans Verkuil 		0x00010001, 0xfff8fff9, 0x001f0015, 0xffafffd3,
332057a3afc5SHans Verkuil 		0x00a80050, 0xfed3ff82, 0x01e900b4, 0xfd20ff12,
332157a3afc5SHans Verkuil 		0x04130128, 0xfa82fea4, 0x07150183, 0xf734fe68,
332257a3afc5SHans Verkuil 		0x0a8d0197, 0xf3bdfe84, 0x0dd50148, 0xf0d5ff03,
332357a3afc5SHans Verkuil 		0x103100a0, 0xef2bffc9, 0x110d0000,
332457a3afc5SHans Verkuil 	}, {	// 12.7 MHz
332557a3afc5SHans Verkuil 		0x00000002, 0xfffafff2, 0x00170027, 0xffc1ffab,
332657a3afc5SHans Verkuil 		0x00880098, 0xff04ff10, 0x01a60159, 0xfd75fe34,
332757a3afc5SHans Verkuil 		0x03b00240, 0xfaeffd58, 0x06a702f9, 0xf79dfcda,
332857a3afc5SHans Verkuil 		0x0a310326, 0xf407fd0d, 0x0d9f028e, 0xf0f6fe06,
332957a3afc5SHans Verkuil 		0x10210140, 0xef2fff93, 0x110d0000,
333057a3afc5SHans Verkuil 	}, {	// 12.8 MHz
333157a3afc5SHans Verkuil 		0x00000003, 0xfffeffef, 0x000c0034, 0xffdbff8f,
333257a3afc5SHans Verkuil 		0x005800ce, 0xff4ffeb6, 0x013c01e1, 0xfdfbfd76,
333357a3afc5SHans Verkuil 		0x03110337, 0xfb9dfc2a, 0x05f40453, 0xf848fb63,
333457a3afc5SHans Verkuil 		0x099904a5, 0xf482fb9f, 0x0d4603ce, 0xf12dfd0c,
333557a3afc5SHans Verkuil 		0x100701df, 0xef36ff5c, 0x110d0000,
333657a3afc5SHans Verkuil 	}, {	// 12.9 MHz
333757a3afc5SHans Verkuil 		0x00000003, 0x0001ffee, 0xffff0038, 0xfffbff82,
333857a3afc5SHans Verkuil 		0x001d00ec, 0xffadfe7c, 0x00b70242, 0xfea9fce5,
333957a3afc5SHans Verkuil 		0x024103ff, 0xfc85fb2a, 0x05040587, 0xf930fa0a,
334057a3afc5SHans Verkuil 		0x08ca060e, 0xf52bfa40, 0x0ccb0507, 0xf179fc15,
334157a3afc5SHans Verkuil 		0x0fe3027d, 0xef3fff25, 0x110d0000,
334257a3afc5SHans Verkuil 	}, {	// 13.0 MHz
334357a3afc5SHans Verkuil 		0x00000002, 0x0005fff0, 0xfff20034, 0x001bff85,
334457a3afc5SHans Verkuil 		0xffdf00f0, 0x0014fe68, 0x00200272, 0xff71fc8b,
334557a3afc5SHans Verkuil 		0x014d048d, 0xfd9afa61, 0x03e00688, 0xfa4ef8da,
334657a3afc5SHans Verkuil 		0x07c80759, 0xf600f8f4, 0x0c2f0637, 0xf1dbfb22,
334757a3afc5SHans Verkuil 		0x0fb4031b, 0xef4bfeef, 0x110d0000,
334857a3afc5SHans Verkuil 	}, {	// 13.1 MHz
334957a3afc5SHans Verkuil 		0xffff0001, 0x0007fff5, 0xffe70028, 0x0037ff98,
335057a3afc5SHans Verkuil 		0xffa400d8, 0x0079fe7c, 0xff87026f, 0x0043fc6e,
335157a3afc5SHans Verkuil 		0x004404da, 0xfecef9da, 0x0294074e, 0xfb99f7db,
335257a3afc5SHans Verkuil 		0x06980881, 0xf6fef7be, 0x0b730759, 0xf251fa33,
335357a3afc5SHans Verkuil 		0x0f7b03b8, 0xef5afeb8, 0x110d0000,
335457a3afc5SHans Verkuil 	}, {	// 13.2 MHz
335557a3afc5SHans Verkuil 		0xffff0000, 0x0008fffc, 0xffe00017, 0x004cffb9,
335657a3afc5SHans Verkuil 		0xff7500a8, 0x00d1feb6, 0xfef90238, 0x0111fc91,
335757a3afc5SHans Verkuil 		0xff3604df, 0x0012f99b, 0x012d07d2, 0xfd07f714,
335857a3afc5SHans Verkuil 		0x0542097e, 0xf81ff6a4, 0x0a9a086e, 0xf2dbf94b,
335957a3afc5SHans Verkuil 		0x0f380453, 0xef6cfe82, 0x110d0000,
336057a3afc5SHans Verkuil 	}, {	// 13.3 MHz
336157a3afc5SHans Verkuil 		0xffffffff, 0x00080003, 0xffde0001, 0x0056ffe3,
336257a3afc5SHans Verkuil 		0xff570064, 0x0113ff10, 0xfe8201d2, 0x01cafcf0,
336357a3afc5SHans Verkuil 		0xfe35049e, 0x0155f9a6, 0xffba080e, 0xfe8cf689,
336457a3afc5SHans Verkuil 		0x03ce0a4e, 0xf961f5a8, 0x09a50971, 0xf379f869,
336557a3afc5SHans Verkuil 		0x0eeb04ec, 0xef80fe4b, 0x110d0000,
336657a3afc5SHans Verkuil 	}, {	// 13.4 MHz
336757a3afc5SHans Verkuil 		0x0000fffe, 0x0007000a, 0xffe2ffec, 0x00540012,
336857a3afc5SHans Verkuil 		0xff4e0015, 0x0137ff82, 0xfe2e0145, 0x0260fd86,
336957a3afc5SHans Verkuil 		0xfd51041a, 0x0287f9fb, 0xfe4a0802, 0x001df63f,
337057a3afc5SHans Verkuil 		0x02430aeb, 0xfabdf4ce, 0x08970a62, 0xf428f78f,
337157a3afc5SHans Verkuil 		0x0e950584, 0xef97fe15, 0x110d0000,
337257a3afc5SHans Verkuil 	}, {	// 13.5 MHz
337357a3afc5SHans Verkuil 		0x0000fffd, 0x0004000f, 0xffeaffda, 0x0046003d,
337457a3afc5SHans Verkuil 		0xff5affc4, 0x013b0000, 0xfe04009d, 0x02c8fe48,
337557a3afc5SHans Verkuil 		0xfc99035a, 0x0397fa96, 0xfcec07ad, 0x01adf637,
337657a3afc5SHans Verkuil 		0x00ac0b53, 0xfc2ef419, 0x07730b3e, 0xf4e9f6bd,
337757a3afc5SHans Verkuil 		0x0e35061a, 0xefb1fddf, 0x110d0000,
337857a3afc5SHans Verkuil 	}, {	// 13.6 MHz
337957a3afc5SHans Verkuil 		0x0000fffd, 0x00000012, 0xfff6ffcd, 0x002f0061,
338057a3afc5SHans Verkuil 		0xff7bff79, 0x011e007e, 0xfe08ffe8, 0x02f9ff28,
338157a3afc5SHans Verkuil 		0xfc17026a, 0x0479fb70, 0xfbad0713, 0x032ff672,
338257a3afc5SHans Verkuil 		0xff100b83, 0xfdaff38b, 0x063c0c04, 0xf5baf5f5,
338357a3afc5SHans Verkuil 		0x0dcc06ae, 0xefcdfda8, 0x110d0000,
338457a3afc5SHans Verkuil 	}, {	// 13.7 MHz
338557a3afc5SHans Verkuil 		0x0000fffd, 0xfffd0012, 0x0004ffc8, 0x00100078,
338657a3afc5SHans Verkuil 		0xffacff3e, 0x00e200f0, 0xfe39ff35, 0x02f10017,
338757a3afc5SHans Verkuil 		0xfbd30156, 0x0521fc7f, 0xfa9c0638, 0x0499f6ee,
338857a3afc5SHans Verkuil 		0xfd7a0b7c, 0xff39f325, 0x04f40cb3, 0xf69af537,
338957a3afc5SHans Verkuil 		0x0d5a073f, 0xefecfd72, 0x110d0000,
339057a3afc5SHans Verkuil 	}, {	// 13.8 MHz
339157a3afc5SHans Verkuil 		0x0001fffe, 0xfffa000e, 0x0011ffcb, 0xfff0007f,
339257a3afc5SHans Verkuil 		0xffe7ff19, 0x008f014a, 0xfe94fe93, 0x02b00105,
339357a3afc5SHans Verkuil 		0xfbd3002f, 0x0585fdb7, 0xf9c10525, 0x05def7a8,
339457a3afc5SHans Verkuil 		0xfbf20b3c, 0x00c7f2e9, 0x03a00d48, 0xf787f484,
339557a3afc5SHans Verkuil 		0x0cdf07cd, 0xf00dfd3c, 0x110d0000,
339657a3afc5SHans Verkuil 	}, {	// 13.9 MHz
339757a3afc5SHans Verkuil 		0x00010000, 0xfff80008, 0x001bffd7, 0xffd10076,
339857a3afc5SHans Verkuil 		0x0026ff0e, 0x002c0184, 0xff0ffe10, 0x023b01e0,
339957a3afc5SHans Verkuil 		0xfc17ff06, 0x05a2ff09, 0xf92703e4, 0x06f4f89b,
340057a3afc5SHans Verkuil 		0xfa820ac5, 0x0251f2d9, 0x02430dc3, 0xf881f3dc,
340157a3afc5SHans Verkuil 		0x0c5c0859, 0xf031fd06, 0x110d0000,
340257a3afc5SHans Verkuil 	}, {	// 14.0 MHz
340357a3afc5SHans Verkuil 		0x00010001, 0xfff80001, 0x0021ffe8, 0xffba005d,
340457a3afc5SHans Verkuil 		0x0060ff1f, 0xffc40198, 0xffa0fdb5, 0x019a029a,
340557a3afc5SHans Verkuil 		0xfc99fdea, 0x05750067, 0xf8d4027f, 0x07d4f9c0,
340657a3afc5SHans Verkuil 		0xf9320a1a, 0x03d2f2f3, 0x00df0e22, 0xf986f341,
340757a3afc5SHans Verkuil 		0x0bd108e2, 0xf058fcd1, 0x110d0000,
340857a3afc5SHans Verkuil 	}, {	// 14.1 MHz
340957a3afc5SHans Verkuil 		0x00000002, 0xfff9fffa, 0x0021fffd, 0xffac0038,
341057a3afc5SHans Verkuil 		0x008eff4a, 0xff630184, 0x003afd8b, 0x00da0326,
341157a3afc5SHans Verkuil 		0xfd51fced, 0x050101c0, 0xf8cb0103, 0x0876fb10,
341257a3afc5SHans Verkuil 		0xf80a093e, 0x0543f338, 0xff7a0e66, 0xfa94f2b2,
341357a3afc5SHans Verkuil 		0x0b3f0967, 0xf081fc9b, 0x110d0000,
341457a3afc5SHans Verkuil 	}, {	// 14.2 MHz
341557a3afc5SHans Verkuil 		0x00000003, 0xfffbfff3, 0x001d0013, 0xffaa000b,
341657a3afc5SHans Verkuil 		0x00aaff89, 0xff13014a, 0x00cefd95, 0x000a037b,
341757a3afc5SHans Verkuil 		0xfe35fc1d, 0x044c0305, 0xf90cff7e, 0x08d5fc81,
341857a3afc5SHans Verkuil 		0xf7100834, 0x069ff3a7, 0xfe160e8d, 0xfbaaf231,
341957a3afc5SHans Verkuil 		0x0aa509e9, 0xf0adfc65, 0x110d0000,
342057a3afc5SHans Verkuil 	}, {	// 14.3 MHz
342157a3afc5SHans Verkuil 		0x00000003, 0xffffffef, 0x00140025, 0xffb4ffdd,
342257a3afc5SHans Verkuil 		0x00b2ffd6, 0xfedb00f0, 0x0150fdd3, 0xff380391,
342357a3afc5SHans Verkuil 		0xff36fb85, 0x035e0426, 0xf994fdfe, 0x08eefe0b,
342457a3afc5SHans Verkuil 		0xf6490702, 0x07e1f43e, 0xfcb60e97, 0xfcc6f1be,
342557a3afc5SHans Verkuil 		0x0a040a67, 0xf0dbfc30, 0x110d0000,
342657a3afc5SHans Verkuil 	}, {	// 14.4 MHz
342757a3afc5SHans Verkuil 		0x00000003, 0x0002ffee, 0x00070033, 0xffc9ffb4,
342857a3afc5SHans Verkuil 		0x00a40027, 0xfec3007e, 0x01b4fe3f, 0xfe760369,
342957a3afc5SHans Verkuil 		0x0044fb2e, 0x02450518, 0xfa5ffc90, 0x08c1ffa1,
343057a3afc5SHans Verkuil 		0xf5bc05ae, 0x0902f4fc, 0xfb600e85, 0xfde7f15a,
343157a3afc5SHans Verkuil 		0x095d0ae2, 0xf10cfbfb, 0x110d0000,
343257a3afc5SHans Verkuil 	}, {	// 14.5 MHz
343357a3afc5SHans Verkuil 		0xffff0002, 0x0005ffef, 0xfffa0038, 0xffe5ff95,
343457a3afc5SHans Verkuil 		0x00820074, 0xfecc0000, 0x01f0fed0, 0xfdd20304,
343557a3afc5SHans Verkuil 		0x014dfb1d, 0x010e05ce, 0xfb64fb41, 0x084e013b,
343657a3afc5SHans Verkuil 		0xf569043e, 0x0a00f5dd, 0xfa150e55, 0xff0bf104,
343757a3afc5SHans Verkuil 		0x08b00b59, 0xf13ffbc6, 0x110d0000,
343857a3afc5SHans Verkuil 	}, {	// 14.6 MHz
343957a3afc5SHans Verkuil 		0xffff0001, 0x0008fff4, 0xffed0035, 0x0005ff83,
344057a3afc5SHans Verkuil 		0x005000b4, 0xfef6ff82, 0x01ffff7a, 0xfd580269,
344157a3afc5SHans Verkuil 		0x0241fb53, 0xffca0640, 0xfc99fa1e, 0x079a02cb,
344257a3afc5SHans Verkuil 		0xf55502ba, 0x0ad5f6e0, 0xf8d90e0a, 0x0031f0bd,
344357a3afc5SHans Verkuil 		0x07fd0bcb, 0xf174fb91, 0x110d0000,
344457a3afc5SHans Verkuil 	}, {	// 14.7 MHz
344557a3afc5SHans Verkuil 		0xffffffff, 0x0009fffb, 0xffe4002a, 0x0025ff82,
344657a3afc5SHans Verkuil 		0x001400e0, 0xff3cff10, 0x01e10030, 0xfd1201a4,
344757a3afc5SHans Verkuil 		0x0311fbcd, 0xfe88066a, 0xfdf1f92f, 0x06aa0449,
344857a3afc5SHans Verkuil 		0xf57e0128, 0x0b7ef801, 0xf7b00da2, 0x0156f086,
344957a3afc5SHans Verkuil 		0x07450c39, 0xf1acfb5c, 0x110d0000,
345057a3afc5SHans Verkuil 	}, {	// 14.8 MHz
345157a3afc5SHans Verkuil 		0x0000fffe, 0x00080002, 0xffdf0019, 0x003fff92,
345257a3afc5SHans Verkuil 		0xffd600f1, 0xff96feb6, 0x019700e1, 0xfd0500c2,
345357a3afc5SHans Verkuil 		0x03b0fc84, 0xfd590649, 0xff5df87f, 0x058505aa,
345457a3afc5SHans Verkuil 		0xf5e4ff91, 0x0bf9f93c, 0xf69d0d20, 0x0279f05e,
345557a3afc5SHans Verkuil 		0x06880ca3, 0xf1e6fb28, 0x110d0000,
345657a3afc5SHans Verkuil 	}, {	// 14.9 MHz
345757a3afc5SHans Verkuil 		0x0000fffd, 0x00060009, 0xffdf0004, 0x0051ffb0,
345857a3afc5SHans Verkuil 		0xff9d00e8, 0xfffcfe7c, 0x01280180, 0xfd32ffd2,
345957a3afc5SHans Verkuil 		0x0413fd6e, 0xfc4d05df, 0x00d1f812, 0x043506e4,
346057a3afc5SHans Verkuil 		0xf685fdfb, 0x0c43fa8d, 0xf5a10c83, 0x0399f046,
346157a3afc5SHans Verkuil 		0x05c70d08, 0xf222faf3, 0x110d0000,
346257a3afc5SHans Verkuil 	}, {	// 15.0 MHz
346357a3afc5SHans Verkuil 		0x0000fffd, 0x0003000f, 0xffe5ffef, 0x0057ffd9,
346457a3afc5SHans Verkuil 		0xff7000c4, 0x0062fe68, 0x009e01ff, 0xfd95fee6,
346557a3afc5SHans Verkuil 		0x0435fe7d, 0xfb710530, 0x023cf7ee, 0x02c307ef,
346657a3afc5SHans Verkuil 		0xf75efc70, 0x0c5cfbef, 0xf4c10bce, 0x04b3f03f,
346757a3afc5SHans Verkuil 		0x05030d69, 0xf261fabf, 0x110d0000,
346857a3afc5SHans Verkuil 	}, {	// 15.1 MHz
346957a3afc5SHans Verkuil 		0x0000fffd, 0xffff0012, 0xffefffdc, 0x00510006,
347057a3afc5SHans Verkuil 		0xff540089, 0x00befe7c, 0x00060253, 0xfe27fe0d,
347157a3afc5SHans Verkuil 		0x0413ffa2, 0xfad10446, 0x0390f812, 0x013b08c3,
347257a3afc5SHans Verkuil 		0xf868faf6, 0x0c43fd5f, 0xf3fd0b02, 0x05c7f046,
347357a3afc5SHans Verkuil 		0x043b0dc4, 0xf2a1fa8b, 0x110d0000,
347457a3afc5SHans Verkuil 	}, {	// 15.2 MHz
347557a3afc5SHans Verkuil 		0x0001fffe, 0xfffc0012, 0xfffbffce, 0x003f0033,
347657a3afc5SHans Verkuil 		0xff4e003f, 0x0106feb6, 0xff6e0276, 0xfeddfd56,
347757a3afc5SHans Verkuil 		0x03b000cc, 0xfa740329, 0x04bff87f, 0xffaa095d,
347857a3afc5SHans Verkuil 		0xf99ef995, 0x0bf9fed8, 0xf3590a1f, 0x06d2f05e,
347957a3afc5SHans Verkuil 		0x03700e1b, 0xf2e4fa58, 0x110d0000,
348057a3afc5SHans Verkuil 	}, {	// 15.3 MHz
348157a3afc5SHans Verkuil 		0x0001ffff, 0xfff9000f, 0x0009ffc8, 0x00250059,
348257a3afc5SHans Verkuil 		0xff5effee, 0x0132ff10, 0xfee30265, 0xffaafccf,
348357a3afc5SHans Verkuil 		0x031101eb, 0xfa6001e8, 0x05bdf92f, 0xfe1b09b6,
348457a3afc5SHans Verkuil 		0xfafaf852, 0x0b7e0055, 0xf2d50929, 0x07d3f086,
348557a3afc5SHans Verkuil 		0x02a30e6c, 0xf329fa24, 0x110d0000,
348657a3afc5SHans Verkuil 	}, {	// 15.4 MHz
348757a3afc5SHans Verkuil 		0x00010001, 0xfff80009, 0x0015ffca, 0x00050074,
348857a3afc5SHans Verkuil 		0xff81ff9f, 0x013dff82, 0xfe710221, 0x007cfc80,
348957a3afc5SHans Verkuil 		0x024102ed, 0xfa940090, 0x0680fa1e, 0xfc9b09cd,
349057a3afc5SHans Verkuil 		0xfc73f736, 0x0ad501d0, 0xf2740820, 0x08c9f0bd,
349157a3afc5SHans Verkuil 		0x01d40eb9, 0xf371f9f1, 0x110d0000,
349257a3afc5SHans Verkuil 	}, {	// 15.5 MHz
349357a3afc5SHans Verkuil 		0x00000002, 0xfff80002, 0x001effd5, 0xffe5007f,
349457a3afc5SHans Verkuil 		0xffb4ff5b, 0x01280000, 0xfe2401b0, 0x0146fc70,
349557a3afc5SHans Verkuil 		0x014d03c6, 0xfb10ff32, 0x0701fb41, 0xfb3709a1,
349657a3afc5SHans Verkuil 		0xfe00f644, 0x0a000345, 0xf2350708, 0x09b2f104,
349757a3afc5SHans Verkuil 		0x01050eff, 0xf3baf9be, 0x110d0000,
349857a3afc5SHans Verkuil 	}, {	// 15.6 MHz
349957a3afc5SHans Verkuil 		0x00000003, 0xfff9fffb, 0x0022ffe6, 0xffc9007a,
350057a3afc5SHans Verkuil 		0xfff0ff29, 0x00f2007e, 0xfe01011b, 0x01f6fc9e,
350157a3afc5SHans Verkuil 		0x00440467, 0xfbccfdde, 0x0738fc90, 0xf9f70934,
350257a3afc5SHans Verkuil 		0xff99f582, 0x090204b0, 0xf21a05e1, 0x0a8df15a,
350357a3afc5SHans Verkuil 		0x00340f41, 0xf405f98b, 0x110d0000,
350457a3afc5SHans Verkuil 	}, {	// 15.7 MHz
350557a3afc5SHans Verkuil 		0x00000003, 0xfffcfff4, 0x0020fffa, 0xffb40064,
350657a3afc5SHans Verkuil 		0x002fff11, 0x00a400f0, 0xfe0d006e, 0x0281fd09,
350757a3afc5SHans Verkuil 		0xff3604c9, 0xfcbffca2, 0x0726fdfe, 0xf8e80888,
350857a3afc5SHans Verkuil 		0x0134f4f3, 0x07e1060c, 0xf22304af, 0x0b59f1be,
350957a3afc5SHans Verkuil 		0xff640f7d, 0xf452f959, 0x110d0000,
351057a3afc5SHans Verkuil 	}, {	// 15.8 MHz
351157a3afc5SHans Verkuil 		0x00000003, 0x0000fff0, 0x001a0010, 0xffaa0041,
351257a3afc5SHans Verkuil 		0x0067ff13, 0x0043014a, 0xfe46ffb9, 0x02dbfda8,
351357a3afc5SHans Verkuil 		0xfe3504e5, 0xfddcfb8d, 0x06c9ff7e, 0xf81107a2,
351457a3afc5SHans Verkuil 		0x02c9f49a, 0x069f0753, 0xf2500373, 0x0c14f231,
351557a3afc5SHans Verkuil 		0xfe930fb3, 0xf4a1f927, 0x110d0000,
351657a3afc5SHans Verkuil 	}, {	// 15.9 MHz
351757a3afc5SHans Verkuil 		0xffff0002, 0x0003ffee, 0x000f0023, 0xffac0016,
351857a3afc5SHans Verkuil 		0x0093ff31, 0xffdc0184, 0xfea6ff09, 0x02fdfe70,
351957a3afc5SHans Verkuil 		0xfd5104ba, 0xff15faac, 0x06270103, 0xf7780688,
352057a3afc5SHans Verkuil 		0x044df479, 0x05430883, 0xf2a00231, 0x0cbef2b2,
352157a3afc5SHans Verkuil 		0xfdc40fe3, 0xf4f2f8f5, 0x110d0000,
352257a3afc5SHans Verkuil 	}, {	// 16.0 MHz
352357a3afc5SHans Verkuil 		0xffff0001, 0x0006ffef, 0x00020031, 0xffbaffe8,
352457a3afc5SHans Verkuil 		0x00adff66, 0xff790198, 0xff26fe6e, 0x02e5ff55,
352557a3afc5SHans Verkuil 		0xfc99044a, 0x005bfa09, 0x0545027f, 0xf7230541,
352657a3afc5SHans Verkuil 		0x05b8f490, 0x03d20997, 0xf31300eb, 0x0d55f341,
352757a3afc5SHans Verkuil 		0xfcf6100e, 0xf544f8c3, 0x110d0000,
352857a3afc5SHans Verkuil 	}
352957a3afc5SHans Verkuil };
353057a3afc5SHans Verkuil 
cx23885_dif_setup(struct i2c_client * client,u32 ifHz)3531efe1724aSMauro Carvalho Chehab static void cx23885_dif_setup(struct i2c_client *client, u32 ifHz)
353274900b47SSteven Toth {
353374900b47SSteven Toth 	u64 pll_freq;
353474900b47SSteven Toth 	u32 pll_freq_word;
353557a3afc5SHans Verkuil 	const u32 *coeffs;
353674900b47SSteven Toth 
353774900b47SSteven Toth 	v4l_dbg(1, cx25840_debug, client, "%s(%d)\n", __func__, ifHz);
353874900b47SSteven Toth 
353974900b47SSteven Toth 	/* Assuming TV */
354074900b47SSteven Toth 	/* Calculate the PLL frequency word based on the adjusted ifHz */
35413308e2b5SMauro Carvalho Chehab 	pll_freq = div_u64((u64)ifHz * 268435456, 50000000);
354274900b47SSteven Toth 	pll_freq_word = (u32)pll_freq;
354374900b47SSteven Toth 
354474900b47SSteven Toth 	cx25840_write4(client, DIF_PLL_FREQ_WORD,  pll_freq_word);
354574900b47SSteven Toth 
354674900b47SSteven Toth 	/* Round down to the nearest 100KHz */
354774900b47SSteven Toth 	ifHz = (ifHz / 100000) * 100000;
354874900b47SSteven Toth 
354974900b47SSteven Toth 	if (ifHz < 3000000)
355074900b47SSteven Toth 		ifHz = 3000000;
355174900b47SSteven Toth 
355274900b47SSteven Toth 	if (ifHz > 16000000)
355374900b47SSteven Toth 		ifHz = 16000000;
355474900b47SSteven Toth 
355574900b47SSteven Toth 	v4l_dbg(1, cx25840_debug, client, "%s(%d) again\n", __func__, ifHz);
355674900b47SSteven Toth 
355757a3afc5SHans Verkuil 	coeffs = ifhz_coeffs[(ifHz - 3000000) / 100000];
355857a3afc5SHans Verkuil 	cx25840_write4(client, DIF_BPF_COEFF01, coeffs[0]);
355957a3afc5SHans Verkuil 	cx25840_write4(client, DIF_BPF_COEFF23, coeffs[1]);
356057a3afc5SHans Verkuil 	cx25840_write4(client, DIF_BPF_COEFF45, coeffs[2]);
356157a3afc5SHans Verkuil 	cx25840_write4(client, DIF_BPF_COEFF67, coeffs[3]);
356257a3afc5SHans Verkuil 	cx25840_write4(client, DIF_BPF_COEFF89, coeffs[4]);
356357a3afc5SHans Verkuil 	cx25840_write4(client, DIF_BPF_COEFF1011, coeffs[5]);
356457a3afc5SHans Verkuil 	cx25840_write4(client, DIF_BPF_COEFF1213, coeffs[6]);
356557a3afc5SHans Verkuil 	cx25840_write4(client, DIF_BPF_COEFF1415, coeffs[7]);
356657a3afc5SHans Verkuil 	cx25840_write4(client, DIF_BPF_COEFF1617, coeffs[8]);
356757a3afc5SHans Verkuil 	cx25840_write4(client, DIF_BPF_COEFF1819, coeffs[9]);
356857a3afc5SHans Verkuil 	cx25840_write4(client, DIF_BPF_COEFF2021, coeffs[10]);
356957a3afc5SHans Verkuil 	cx25840_write4(client, DIF_BPF_COEFF2223, coeffs[11]);
357057a3afc5SHans Verkuil 	cx25840_write4(client, DIF_BPF_COEFF2425, coeffs[12]);
357157a3afc5SHans Verkuil 	cx25840_write4(client, DIF_BPF_COEFF2627, coeffs[13]);
357257a3afc5SHans Verkuil 	cx25840_write4(client, DIF_BPF_COEFF2829, coeffs[14]);
357357a3afc5SHans Verkuil 	cx25840_write4(client, DIF_BPF_COEFF3031, coeffs[15]);
357457a3afc5SHans Verkuil 	cx25840_write4(client, DIF_BPF_COEFF3233, coeffs[16]);
357557a3afc5SHans Verkuil 	cx25840_write4(client, DIF_BPF_COEFF3435, coeffs[17]);
357657a3afc5SHans Verkuil 	cx25840_write4(client, DIF_BPF_COEFF36, coeffs[18]);
357774900b47SSteven Toth }
357874900b47SSteven Toth 
cx23888_std_setup(struct i2c_client * client)3579ba50e7e1SDevin Heitmueller static void cx23888_std_setup(struct i2c_client *client)
358074900b47SSteven Toth {
358174900b47SSteven Toth 	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
358274900b47SSteven Toth 	v4l2_std_id std = state->std;
358374900b47SSteven Toth 	u32 ifHz;
358474900b47SSteven Toth 
358574900b47SSteven Toth 	cx25840_write4(client, 0x478, 0x6628021F);
358674900b47SSteven Toth 	cx25840_write4(client, 0x400, 0x0);
358774900b47SSteven Toth 	cx25840_write4(client, 0x4b4, 0x20524030);
358874900b47SSteven Toth 	cx25840_write4(client, 0x47c, 0x010a8263);
358974900b47SSteven Toth 
3590bfd1bbfbSHans Verkuil 	if (std & V4L2_STD_525_60) {
359174900b47SSteven Toth 		v4l_dbg(1, cx25840_debug, client, "%s() Selecting NTSC",
359274900b47SSteven Toth 			__func__);
359374900b47SSteven Toth 
359474900b47SSteven Toth 		/* Horiz / vert timing */
359574900b47SSteven Toth 		cx25840_write4(client, 0x428, 0x1e1e601a);
359674900b47SSteven Toth 		cx25840_write4(client, 0x424, 0x5b2d007a);
359774900b47SSteven Toth 
359874900b47SSteven Toth 		/* DIF NTSC */
359974900b47SSteven Toth 		cx25840_write4(client, 0x304, 0x6503bc0c);
360074900b47SSteven Toth 		cx25840_write4(client, 0x308, 0xbd038c85);
360174900b47SSteven Toth 		cx25840_write4(client, 0x30c, 0x1db4640a);
360274900b47SSteven Toth 		cx25840_write4(client, 0x310, 0x00008800);
360374900b47SSteven Toth 		cx25840_write4(client, 0x314, 0x44400400);
360474900b47SSteven Toth 		cx25840_write4(client, 0x32c, 0x0c800800);
360574900b47SSteven Toth 		cx25840_write4(client, 0x330, 0x27000100);
360674900b47SSteven Toth 		cx25840_write4(client, 0x334, 0x1f296e1f);
360774900b47SSteven Toth 		cx25840_write4(client, 0x338, 0x009f50c1);
360874900b47SSteven Toth 		cx25840_write4(client, 0x340, 0x1befbf06);
360974900b47SSteven Toth 		cx25840_write4(client, 0x344, 0x000035e8);
361074900b47SSteven Toth 
361174900b47SSteven Toth 		/* DIF I/F */
361274900b47SSteven Toth 		ifHz = 5400000;
361374900b47SSteven Toth 
361474900b47SSteven Toth 	} else {
361574900b47SSteven Toth 		v4l_dbg(1, cx25840_debug, client, "%s() Selecting PAL-BG",
361674900b47SSteven Toth 			__func__);
361774900b47SSteven Toth 
361874900b47SSteven Toth 		/* Horiz / vert timing */
361974900b47SSteven Toth 		cx25840_write4(client, 0x428, 0x28244024);
362074900b47SSteven Toth 		cx25840_write4(client, 0x424, 0x5d2d0084);
362174900b47SSteven Toth 
362274900b47SSteven Toth 		/* DIF */
362374900b47SSteven Toth 		cx25840_write4(client, 0x304, 0x6503bc0c);
362474900b47SSteven Toth 		cx25840_write4(client, 0x308, 0xbd038c85);
362574900b47SSteven Toth 		cx25840_write4(client, 0x30c, 0x1db4640a);
362674900b47SSteven Toth 		cx25840_write4(client, 0x310, 0x00008800);
362774900b47SSteven Toth 		cx25840_write4(client, 0x314, 0x44400600);
362874900b47SSteven Toth 		cx25840_write4(client, 0x32c, 0x0c800800);
362974900b47SSteven Toth 		cx25840_write4(client, 0x330, 0x27000100);
363074900b47SSteven Toth 		cx25840_write4(client, 0x334, 0x213530ec);
363174900b47SSteven Toth 		cx25840_write4(client, 0x338, 0x00a65ba8);
363274900b47SSteven Toth 		cx25840_write4(client, 0x340, 0x1befbf06);
363374900b47SSteven Toth 		cx25840_write4(client, 0x344, 0x000035e8);
363474900b47SSteven Toth 
363574900b47SSteven Toth 		/* DIF I/F */
363674900b47SSteven Toth 		ifHz = 6000000;
363774900b47SSteven Toth 	}
363874900b47SSteven Toth 
363974900b47SSteven Toth 	cx23885_dif_setup(client, ifHz);
364074900b47SSteven Toth 
364174900b47SSteven Toth 	/* Explicitly ensure the inputs are reconfigured after
364274900b47SSteven Toth 	 * a standard change.
364374900b47SSteven Toth 	 */
364474900b47SSteven Toth 	set_input(client, state->vid_input, state->aud_input);
364574900b47SSteven Toth }
364674900b47SSteven Toth 
364774900b47SSteven Toth /* ----------------------------------------------------------------------- */
364874900b47SSteven Toth 
3649e34e658bSHans Verkuil static const struct v4l2_ctrl_ops cx25840_ctrl_ops = {
3650e34e658bSHans Verkuil 	.s_ctrl = cx25840_s_ctrl,
3651e34e658bSHans Verkuil };
3652e34e658bSHans Verkuil 
36539357b31cSHans Verkuil static const struct v4l2_subdev_core_ops cx25840_core_ops = {
36549357b31cSHans Verkuil 	.log_status = cx25840_log_status,
36559357b31cSHans Verkuil 	.reset = cx25840_reset,
3656e81a9076SMaciej S. Szmigiero 	/* calling the (optional) init op will turn on the generic mode */
3657e81a9076SMaciej S. Szmigiero 	.init = cx25840_init,
3658cc26b076SHans Verkuil 	.load_fw = cx25840_load_fw,
3659d06d5777SAndy Walls 	.s_io_pin_config = common_s_io_pin_config,
36609357b31cSHans Verkuil #ifdef CONFIG_VIDEO_ADV_DEBUG
36619357b31cSHans Verkuil 	.g_register = cx25840_g_register,
36629357b31cSHans Verkuil 	.s_register = cx25840_s_register,
36639357b31cSHans Verkuil #endif
366452fd3ddaSAndy Walls 	.interrupt_service_routine = cx25840_irq_handler,
36659357b31cSHans Verkuil };
36669357b31cSHans Verkuil 
36679357b31cSHans Verkuil static const struct v4l2_subdev_tuner_ops cx25840_tuner_ops = {
36689357b31cSHans Verkuil 	.s_frequency = cx25840_s_frequency,
36699357b31cSHans Verkuil 	.s_radio = cx25840_s_radio,
36709357b31cSHans Verkuil 	.g_tuner = cx25840_g_tuner,
36719357b31cSHans Verkuil 	.s_tuner = cx25840_s_tuner,
36729357b31cSHans Verkuil };
36739357b31cSHans Verkuil 
36749357b31cSHans Verkuil static const struct v4l2_subdev_audio_ops cx25840_audio_ops = {
36759357b31cSHans Verkuil 	.s_clock_freq = cx25840_s_clock_freq,
36769357b31cSHans Verkuil 	.s_routing = cx25840_s_audio_routing,
36773ccc646bSAndy Walls 	.s_stream = cx25840_s_audio_stream,
36789357b31cSHans Verkuil };
36799357b31cSHans Verkuil 
36809357b31cSHans Verkuil static const struct v4l2_subdev_video_ops cx25840_video_ops = {
3681763549a3SMaciej S. Szmigiero 	.g_std = cx25840_g_std,
36828774bed9SLaurent Pinchart 	.s_std = cx25840_s_std,
368360acc4abSMaciej S. Szmigiero 	.querystd = cx25840_querystd,
36849357b31cSHans Verkuil 	.s_routing = cx25840_s_video_routing,
36859357b31cSHans Verkuil 	.s_stream = cx25840_s_stream,
3686a21df45dSSteven Toth 	.g_input_status = cx25840_g_input_status,
36879357b31cSHans Verkuil };
36889357b31cSHans Verkuil 
368932cd527fSHans Verkuil static const struct v4l2_subdev_vbi_ops cx25840_vbi_ops = {
369032cd527fSHans Verkuil 	.decode_vbi_line = cx25840_decode_vbi_line,
36915393db43SHans Verkuil 	.s_raw_fmt = cx25840_s_raw_fmt,
36925393db43SHans Verkuil 	.s_sliced_fmt = cx25840_s_sliced_fmt,
36935393db43SHans Verkuil 	.g_sliced_fmt = cx25840_g_sliced_fmt,
369432cd527fSHans Verkuil };
369532cd527fSHans Verkuil 
36966e80c473SHans Verkuil static const struct v4l2_subdev_pad_ops cx25840_pad_ops = {
36976e80c473SHans Verkuil 	.set_fmt = cx25840_set_fmt,
36986e80c473SHans Verkuil };
36996e80c473SHans Verkuil 
37009357b31cSHans Verkuil static const struct v4l2_subdev_ops cx25840_ops = {
37019357b31cSHans Verkuil 	.core = &cx25840_core_ops,
37029357b31cSHans Verkuil 	.tuner = &cx25840_tuner_ops,
37039357b31cSHans Verkuil 	.audio = &cx25840_audio_ops,
37049357b31cSHans Verkuil 	.video = &cx25840_video_ops,
370532cd527fSHans Verkuil 	.vbi = &cx25840_vbi_ops,
37066e80c473SHans Verkuil 	.pad = &cx25840_pad_ops,
370752fd3ddaSAndy Walls 	.ir = &cx25840_ir_ops,
37089357b31cSHans Verkuil };
37099357b31cSHans Verkuil 
3710bd985160SHans Verkuil /* ----------------------------------------------------------------------- */
3711bd985160SHans Verkuil 
get_cx2388x_ident(struct i2c_client * client)3712c7dd1ecdSAndy Walls static u32 get_cx2388x_ident(struct i2c_client *client)
3713c7dd1ecdSAndy Walls {
3714c7dd1ecdSAndy Walls 	u32 ret;
3715c7dd1ecdSAndy Walls 
3716c7dd1ecdSAndy Walls 	/* Come out of digital power down */
3717c7dd1ecdSAndy Walls 	cx25840_write(client, 0x000, 0);
3718c7dd1ecdSAndy Walls 
371910a34367SMauro Carvalho Chehab 	/*
372010a34367SMauro Carvalho Chehab 	 * Detecting whether the part is cx23885/7/8 is more
37218c2d7821SSteven Toth 	 * difficult than it needs to be. No ID register. Instead we
37228c2d7821SSteven Toth 	 * probe certain registers indicated in the datasheets to look
372310a34367SMauro Carvalho Chehab 	 * for specific defaults that differ between the silicon designs.
372410a34367SMauro Carvalho Chehab 	 */
37258c2d7821SSteven Toth 
37268c2d7821SSteven Toth 	/* It's either 885/7 if the IR Tx Clk Divider register exists */
3727c7dd1ecdSAndy Walls 	if (cx25840_read4(client, 0x204) & 0xffff) {
372810a34367SMauro Carvalho Chehab 		/*
372910a34367SMauro Carvalho Chehab 		 * CX23885 returns bogus repetitive byte values for the DIF,
373010a34367SMauro Carvalho Chehab 		 * which doesn't exist for it. (Ex. 8a8a8a8a or 31313131)
373110a34367SMauro Carvalho Chehab 		 */
37328c2d7821SSteven Toth 		ret = cx25840_read4(client, 0x300);
37338c2d7821SSteven Toth 		if (((ret & 0xffff0000) >> 16) == (ret & 0xffff)) {
37348c2d7821SSteven Toth 			/* No DIF */
373529d6a98bSHans Verkuil 			ret = CX23885_AV;
37368c2d7821SSteven Toth 		} else {
373710a34367SMauro Carvalho Chehab 			/*
373810a34367SMauro Carvalho Chehab 			 * CX23887 has a broken DIF, but the registers
373910a34367SMauro Carvalho Chehab 			 * appear valid (but unused), good enough to detect.
374010a34367SMauro Carvalho Chehab 			 */
374129d6a98bSHans Verkuil 			ret = CX23887_AV;
37428c2d7821SSteven Toth 		}
3743c7dd1ecdSAndy Walls 	} else if (cx25840_read4(client, 0x300) & 0x0fffffff) {
3744c7dd1ecdSAndy Walls 		/* DIF PLL Freq Word reg exists; chip must be a CX23888 */
374529d6a98bSHans Verkuil 		ret = CX23888_AV;
3746c7dd1ecdSAndy Walls 	} else {
37478c2d7821SSteven Toth 		v4l_err(client, "Unable to detect h/w, assuming cx23887\n");
374829d6a98bSHans Verkuil 		ret = CX23887_AV;
3749c7dd1ecdSAndy Walls 	}
3750c7dd1ecdSAndy Walls 
3751c7dd1ecdSAndy Walls 	/* Back into digital power down */
3752c7dd1ecdSAndy Walls 	cx25840_write(client, 0x000, 2);
3753c7dd1ecdSAndy Walls 	return ret;
3754c7dd1ecdSAndy Walls }
3755c7dd1ecdSAndy Walls 
cx25840_probe(struct i2c_client * client)37563c6d4866SUwe Kleine-König static int cx25840_probe(struct i2c_client *client)
3757bd985160SHans Verkuil {
3758bd985160SHans Verkuil 	struct cx25840_state *state;
37599357b31cSHans Verkuil 	struct v4l2_subdev *sd;
3760e34e658bSHans Verkuil 	int default_volume;
376129d6a98bSHans Verkuil 	u32 id;
3762bd985160SHans Verkuil 	u16 device_id;
37638cd61969SMauro Carvalho Chehab #if defined(CONFIG_MEDIA_CONTROLLER)
37648cd61969SMauro Carvalho Chehab 	int ret;
37658cd61969SMauro Carvalho Chehab #endif
3766bd985160SHans Verkuil 
3767188f3457SHans Verkuil 	/* Check if the adapter supports the needed features */
3768188f3457SHans Verkuil 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
3769188f3457SHans Verkuil 		return -EIO;
3770188f3457SHans Verkuil 
377110a34367SMauro Carvalho Chehab 	v4l_dbg(1, cx25840_debug, client,
377210a34367SMauro Carvalho Chehab 		"detecting cx25840 client on address 0x%x\n",
377310a34367SMauro Carvalho Chehab 		client->addr << 1);
3774bd985160SHans Verkuil 
3775bd985160SHans Verkuil 	device_id = cx25840_read(client, 0x101) << 8;
3776bd985160SHans Verkuil 	device_id |= cx25840_read(client, 0x100);
3777f234081bSSteven Toth 	v4l_dbg(1, cx25840_debug, client, "device_id = 0x%04x\n", device_id);
3778bd985160SHans Verkuil 
377910a34367SMauro Carvalho Chehab 	/*
378010a34367SMauro Carvalho Chehab 	 * The high byte of the device ID should be
378110a34367SMauro Carvalho Chehab 	 * 0x83 for the cx2583x and 0x84 for the cx2584x
378210a34367SMauro Carvalho Chehab 	 */
3783e2b8cf4cSHans Verkuil 	if ((device_id & 0xff00) == 0x8300) {
378429d6a98bSHans Verkuil 		id = CX25836 + ((device_id >> 4) & 0xf) - 6;
3785c7dd1ecdSAndy Walls 	} else if ((device_id & 0xff00) == 0x8400) {
378629d6a98bSHans Verkuil 		id = CX25840 + ((device_id >> 4) & 0xf);
378700ca7324SHans Verkuil 	} else if (device_id == 0x0000) {
3788c7dd1ecdSAndy Walls 		id = get_cx2388x_ident(client);
3789149783b5SSri Deevi 	} else if ((device_id & 0xfff0) == 0x5A30) {
3790c7dd1ecdSAndy Walls 		/* The CX23100 (0x5A3C = 23100) doesn't have an A/V decoder */
379129d6a98bSHans Verkuil 		id = CX2310X_AV;
3792c7dd1ecdSAndy Walls 	} else if ((device_id & 0xff) == (device_id >> 8)) {
3793c7dd1ecdSAndy Walls 		v4l_err(client,
379472cc0671SMauro Carvalho Chehab 			"likely a confused/unresponsive cx2388[578] A/V decoder found @ 0x%x (%s)\n",
3795c7dd1ecdSAndy Walls 			client->addr << 1, client->adapter->name);
379610a34367SMauro Carvalho Chehab 		v4l_err(client,
379710a34367SMauro Carvalho Chehab 			"A method to reset it from the cx25840 driver software is not known at this time\n");
3798c7dd1ecdSAndy Walls 		return -ENODEV;
3799c7dd1ecdSAndy Walls 	} else {
3800b5fc7144SHans Verkuil 		v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n");
3801188f3457SHans Verkuil 		return -ENODEV;
3802bd985160SHans Verkuil 	}
3803bd985160SHans Verkuil 
3804c02b211dSLaurent Pinchart 	state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
380510a34367SMauro Carvalho Chehab 	if (!state)
380621340ae0SHans Verkuil 		return -ENOMEM;
380721340ae0SHans Verkuil 
38089357b31cSHans Verkuil 	sd = &state->sd;
38099357b31cSHans Verkuil 	v4l2_i2c_subdev_init(sd, client, &cx25840_ops);
38108cd61969SMauro Carvalho Chehab #if defined(CONFIG_MEDIA_CONTROLLER)
381118e8d630SMauro Carvalho Chehab 	/*
381218e8d630SMauro Carvalho Chehab 	 * TODO: add media controller support for analog video inputs like
381318e8d630SMauro Carvalho Chehab 	 * composite, svideo, etc.
381418e8d630SMauro Carvalho Chehab 	 * A real input pad for this analog demod would be like:
381518e8d630SMauro Carvalho Chehab 	 *                 ___________
381618e8d630SMauro Carvalho Chehab 	 * TUNER --------> |         |
381718e8d630SMauro Carvalho Chehab 	 *		   |         |
381818e8d630SMauro Carvalho Chehab 	 * SVIDEO .......> | cx25840 |
381918e8d630SMauro Carvalho Chehab 	 *		   |         |
382018e8d630SMauro Carvalho Chehab 	 * COMPOSITE1 ...> |_________|
382118e8d630SMauro Carvalho Chehab 	 *
382218e8d630SMauro Carvalho Chehab 	 * However, at least for now, there's no much gain on modelling
382318e8d630SMauro Carvalho Chehab 	 * those extra inputs. So, let's add it only when needed.
382418e8d630SMauro Carvalho Chehab 	 */
38257e4f23d5SMauro Carvalho Chehab 	state->pads[CX25840_PAD_INPUT].flags = MEDIA_PAD_FL_SINK;
382646c039d0SCody P Schafer 	state->pads[CX25840_PAD_INPUT].sig_type = PAD_SIGNAL_ANALOG;
38277e4f23d5SMauro Carvalho Chehab 	state->pads[CX25840_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
382846c039d0SCody P Schafer 	state->pads[CX25840_PAD_VID_OUT].sig_type = PAD_SIGNAL_DV;
38294ca72efaSMauro Carvalho Chehab 	sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
38308cd61969SMauro Carvalho Chehab 
3831ab22e77cSMauro Carvalho Chehab 	ret = media_entity_pads_init(&sd->entity, ARRAY_SIZE(state->pads),
383218095107SMauro Carvalho Chehab 				     state->pads);
38338cd61969SMauro Carvalho Chehab 	if (ret < 0) {
38348cd61969SMauro Carvalho Chehab 		v4l_info(client, "failed to initialize media entity!\n");
3835db749359SMauro Carvalho Chehab 		return ret;
38368cd61969SMauro Carvalho Chehab 	}
38378cd61969SMauro Carvalho Chehab #endif
3838e34e658bSHans Verkuil 
3839c7dd1ecdSAndy Walls 	switch (id) {
384029d6a98bSHans Verkuil 	case CX23885_AV:
3841c7dd1ecdSAndy Walls 		v4l_info(client, "cx23885 A/V decoder found @ 0x%x (%s)\n",
3842c7dd1ecdSAndy Walls 			 client->addr << 1, client->adapter->name);
3843c7dd1ecdSAndy Walls 		break;
384429d6a98bSHans Verkuil 	case CX23887_AV:
3845c7dd1ecdSAndy Walls 		v4l_info(client, "cx23887 A/V decoder found @ 0x%x (%s)\n",
3846c7dd1ecdSAndy Walls 			 client->addr << 1, client->adapter->name);
3847c7dd1ecdSAndy Walls 		break;
384829d6a98bSHans Verkuil 	case CX23888_AV:
3849c7dd1ecdSAndy Walls 		v4l_info(client, "cx23888 A/V decoder found @ 0x%x (%s)\n",
3850c7dd1ecdSAndy Walls 			 client->addr << 1, client->adapter->name);
3851c7dd1ecdSAndy Walls 		break;
385229d6a98bSHans Verkuil 	case CX2310X_AV:
3853c7dd1ecdSAndy Walls 		v4l_info(client, "cx%d A/V decoder found @ 0x%x (%s)\n",
3854c7dd1ecdSAndy Walls 			 device_id, client->addr << 1, client->adapter->name);
3855c7dd1ecdSAndy Walls 		break;
385629d6a98bSHans Verkuil 	case CX25840:
385729d6a98bSHans Verkuil 	case CX25841:
385829d6a98bSHans Verkuil 	case CX25842:
385929d6a98bSHans Verkuil 	case CX25843:
386010a34367SMauro Carvalho Chehab 		/*
386110a34367SMauro Carvalho Chehab 		 * Note: revision '(device_id & 0x0f) == 2' was never built.
386210a34367SMauro Carvalho Chehab 		 * The marking skips from 0x1 == 22 to 0x3 == 23.
386310a34367SMauro Carvalho Chehab 		 */
3864fac9e899SHans Verkuil 		v4l_info(client, "cx25%3x-2%x found @ 0x%x (%s)\n",
3865bd985160SHans Verkuil 			 (device_id & 0xfff0) >> 4,
3866c7dd1ecdSAndy Walls 			 (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1
3867c7dd1ecdSAndy Walls 						: (device_id & 0x0f),
386821340ae0SHans Verkuil 			 client->addr << 1, client->adapter->name);
3869c7dd1ecdSAndy Walls 		break;
387029d6a98bSHans Verkuil 	case CX25836:
387129d6a98bSHans Verkuil 	case CX25837:
3872c7dd1ecdSAndy Walls 	default:
3873c7dd1ecdSAndy Walls 		v4l_info(client, "cx25%3x-%x found @ 0x%x (%s)\n",
3874c7dd1ecdSAndy Walls 			 (device_id & 0xfff0) >> 4, device_id & 0x0f,
3875c7dd1ecdSAndy Walls 			 client->addr << 1, client->adapter->name);
3876c7dd1ecdSAndy Walls 		break;
3877c7dd1ecdSAndy Walls 	}
3878bd985160SHans Verkuil 
387921340ae0SHans Verkuil 	state->c = client;
3880a8bbf12aSHans Verkuil 	state->vid_input = CX25840_COMPOSITE7;
3881a8bbf12aSHans Verkuil 	state->aud_input = CX25840_AUDIO8;
38823578d3ddSHans Verkuil 	state->audclk_freq = 48000;
38838a4b275fSHans Verkuil 	state->audmode = V4L2_TUNER_MODE_LANG1;
38843e3bf277SChristopher Neufeld 	state->vbi_line_offset = 8;
3885e2b8cf4cSHans Verkuil 	state->id = id;
38863434eb7eSHans Verkuil 	state->rev = device_id;
3887cdf472d3SHans Verkuil 	state->vbi_regs_offset = id == CX23888_AV ? 0x500 - 0x424 : 0;
3888bfd1bbfbSHans Verkuil 	state->std = V4L2_STD_NTSC_M;
3889e34e658bSHans Verkuil 	v4l2_ctrl_handler_init(&state->hdl, 9);
3890e34e658bSHans Verkuil 	v4l2_ctrl_new_std(&state->hdl, &cx25840_ctrl_ops,
3891e34e658bSHans Verkuil 			  V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
3892e34e658bSHans Verkuil 	v4l2_ctrl_new_std(&state->hdl, &cx25840_ctrl_ops,
3893e34e658bSHans Verkuil 			  V4L2_CID_CONTRAST, 0, 127, 1, 64);
3894e34e658bSHans Verkuil 	v4l2_ctrl_new_std(&state->hdl, &cx25840_ctrl_ops,
3895e34e658bSHans Verkuil 			  V4L2_CID_SATURATION, 0, 127, 1, 64);
3896e34e658bSHans Verkuil 	v4l2_ctrl_new_std(&state->hdl, &cx25840_ctrl_ops,
3897e34e658bSHans Verkuil 			  V4L2_CID_HUE, -128, 127, 1, 0);
3898e34e658bSHans Verkuil 	if (!is_cx2583x(state)) {
3899f23b7952SAndy Walls 		default_volume = cx25840_read(client, 0x8d4);
3900f23b7952SAndy Walls 		/*
3901f23b7952SAndy Walls 		 * Enforce the legacy PVR-350/MSP3400 to PVR-150/CX25843 volume
3902f23b7952SAndy Walls 		 * scale mapping limits to avoid -ERANGE errors when
3903f23b7952SAndy Walls 		 * initializing the volume control
3904f23b7952SAndy Walls 		 */
3905f23b7952SAndy Walls 		if (default_volume > 228) {
3906f23b7952SAndy Walls 			/* Bottom out at -96 dB, v4l2 vol range 0x2e00-0x2fff */
3907f23b7952SAndy Walls 			default_volume = 228;
3908f23b7952SAndy Walls 			cx25840_write(client, 0x8d4, 228);
390910a34367SMauro Carvalho Chehab 		} else if (default_volume < 20) {
3910f23b7952SAndy Walls 			/* Top out at + 8 dB, v4l2 vol range 0xfe00-0xffff */
3911f23b7952SAndy Walls 			default_volume = 20;
3912f23b7952SAndy Walls 			cx25840_write(client, 0x8d4, 20);
3913f23b7952SAndy Walls 		}
3914f23b7952SAndy Walls 		default_volume = (((228 - default_volume) >> 1) + 23) << 9;
3915e34e658bSHans Verkuil 
3916e34e658bSHans Verkuil 		state->volume = v4l2_ctrl_new_std(&state->hdl,
391710a34367SMauro Carvalho Chehab 						  &cx25840_audio_ctrl_ops,
391810a34367SMauro Carvalho Chehab 						  V4L2_CID_AUDIO_VOLUME,
391910a34367SMauro Carvalho Chehab 						  0, 65535, 65535 / 100,
392010a34367SMauro Carvalho Chehab 						  default_volume);
3921e34e658bSHans Verkuil 		state->mute = v4l2_ctrl_new_std(&state->hdl,
392210a34367SMauro Carvalho Chehab 						&cx25840_audio_ctrl_ops,
392310a34367SMauro Carvalho Chehab 						V4L2_CID_AUDIO_MUTE,
3924e34e658bSHans Verkuil 						0, 1, 1, 0);
3925e34e658bSHans Verkuil 		v4l2_ctrl_new_std(&state->hdl, &cx25840_audio_ctrl_ops,
3926e34e658bSHans Verkuil 				  V4L2_CID_AUDIO_BALANCE,
3927e34e658bSHans Verkuil 				  0, 65535, 65535 / 100, 32768);
3928e34e658bSHans Verkuil 		v4l2_ctrl_new_std(&state->hdl, &cx25840_audio_ctrl_ops,
3929e34e658bSHans Verkuil 				  V4L2_CID_AUDIO_BASS,
3930e34e658bSHans Verkuil 				  0, 65535, 65535 / 100, 32768);
3931e34e658bSHans Verkuil 		v4l2_ctrl_new_std(&state->hdl, &cx25840_audio_ctrl_ops,
3932e34e658bSHans Verkuil 				  V4L2_CID_AUDIO_TREBLE,
3933e34e658bSHans Verkuil 				  0, 65535, 65535 / 100, 32768);
3934e34e658bSHans Verkuil 	}
3935e34e658bSHans Verkuil 	sd->ctrl_handler = &state->hdl;
3936e34e658bSHans Verkuil 	if (state->hdl.error) {
3937e34e658bSHans Verkuil 		int err = state->hdl.error;
3938e34e658bSHans Verkuil 
3939e34e658bSHans Verkuil 		v4l2_ctrl_handler_free(&state->hdl);
3940e34e658bSHans Verkuil 		return err;
3941e34e658bSHans Verkuil 	}
39421e6406b8SSven Barth 	if (!is_cx2583x(state))
3943e34e658bSHans Verkuil 		v4l2_ctrl_cluster(2, &state->volume);
3944e34e658bSHans Verkuil 	v4l2_ctrl_handler_setup(&state->hdl);
3945f234081bSSteven Toth 
39463c7c9370SHans Verkuil 	if (client->dev.platform_data) {
39473c7c9370SHans Verkuil 		struct cx25840_platform_data *pdata = client->dev.platform_data;
39483c7c9370SHans Verkuil 
39493c7c9370SHans Verkuil 		state->pvr150_workaround = pdata->pvr150_workaround;
39503c7c9370SHans Verkuil 	}
39513c7c9370SHans Verkuil 
395252fd3ddaSAndy Walls 	cx25840_ir_probe(sd);
3953bd985160SHans Verkuil 	return 0;
3954bd985160SHans Verkuil }
3955bd985160SHans Verkuil 
cx25840_remove(struct i2c_client * client)3956ed5c2f5fSUwe Kleine-König static void cx25840_remove(struct i2c_client *client)
3957bd985160SHans Verkuil {
39589357b31cSHans Verkuil 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
3959e34e658bSHans Verkuil 	struct cx25840_state *state = to_state(sd);
39609357b31cSHans Verkuil 
396152fd3ddaSAndy Walls 	cx25840_ir_remove(sd);
39629357b31cSHans Verkuil 	v4l2_device_unregister_subdev(sd);
3963e34e658bSHans Verkuil 	v4l2_ctrl_handler_free(&state->hdl);
3964bd985160SHans Verkuil }
3965bd985160SHans Verkuil 
3966af294867SJean Delvare static const struct i2c_device_id cx25840_id[] = {
3967cc4cbd4bSUwe Kleine-König 	{ "cx25840" },
3968af294867SJean Delvare 	{ }
3969af294867SJean Delvare };
3970af294867SJean Delvare MODULE_DEVICE_TABLE(i2c, cx25840_id);
3971af294867SJean Delvare 
3972ad62cdfeSHans Verkuil static struct i2c_driver cx25840_driver = {
3973ad62cdfeSHans Verkuil 	.driver = {
3974bd985160SHans Verkuil 		.name	= "cx25840",
3975ad62cdfeSHans Verkuil 	},
3976aaeb31c0SUwe Kleine-König 	.probe		= cx25840_probe,
39771a39275aSHans Verkuil 	.remove		= cx25840_remove,
3978af294867SJean Delvare 	.id_table	= cx25840_id,
3979bd985160SHans Verkuil };
3980ad62cdfeSHans Verkuil 
3981c6e8d86fSAxel Lin module_i2c_driver(cx25840_driver);
3982