19 #include <linux/module.h>
22 #include <linux/errno.h>
23 #include <linux/kernel.h>
25 #include <linux/i2c.h>
26 #include <linux/slab.h>
30 #define DRIVER_NAME "saa7706h"
49 #define SAA7706H_REG_CTRL 0x0fff
50 #define SAA7706H_CTRL_BYP_PLL 0x0001
51 #define SAA7706H_CTRL_PLL_DIV_MASK 0x003e
52 #define SAA7706H_CTRL_PLL3_62975MHZ 0x003e
53 #define SAA7706H_CTRL_DSP_TURBO 0x0040
54 #define SAA7706H_CTRL_PC_RESET_DSP1 0x0080
55 #define SAA7706H_CTRL_PC_RESET_DSP2 0x0100
56 #define SAA7706H_CTRL_DSP1_ROM_EN_MASK 0x0600
57 #define SAA7706H_CTRL_DSP1_FUNC_PROM 0x0000
58 #define SAA7706H_CTRL_DSP2_ROM_EN_MASK 0x1800
59 #define SAA7706H_CTRL_DSP2_FUNC_PROM 0x0000
60 #define SAA7706H_CTRL_DIG_SIL_INTERPOL 0x8000
62 #define SAA7706H_REG_EVALUATION 0x1ff0
63 #define SAA7706H_EVAL_DISABLE_CHARGE_PUMP 0x000001
64 #define SAA7706H_EVAL_DCS_CLOCK 0x000002
65 #define SAA7706H_EVAL_GNDRC1_ENABLE 0x000004
66 #define SAA7706H_EVAL_GNDRC2_ENABLE 0x000008
68 #define SAA7706H_REG_CL_GEN1 0x1ff3
69 #define SAA7706H_CL_GEN1_MIN_LOOPGAIN_MASK 0x00000f
70 #define SAA7706H_CL_GEN1_LOOPGAIN_MASK 0x0000f0
71 #define SAA7706H_CL_GEN1_COARSE_RATION 0xffff00
73 #define SAA7706H_REG_CL_GEN2 0x1ff4
74 #define SAA7706H_CL_GEN2_WSEDGE_FALLING 0x000001
75 #define SAA7706H_CL_GEN2_STOP_VCO 0x000002
76 #define SAA7706H_CL_GEN2_FRERUN 0x000004
77 #define SAA7706H_CL_GEN2_ADAPTIVE 0x000008
78 #define SAA7706H_CL_GEN2_FINE_RATIO_MASK 0x0ffff0
80 #define SAA7706H_REG_CL_GEN4 0x1ff6
81 #define SAA7706H_CL_GEN4_BYPASS_PLL1 0x001000
82 #define SAA7706H_CL_GEN4_PLL1_DIV_MASK 0x03e000
83 #define SAA7706H_CL_GEN4_DSP1_TURBO 0x040000
85 #define SAA7706H_REG_SEL 0x1ff7
86 #define SAA7706H_SEL_DSP2_SRCA_MASK 0x000007
87 #define SAA7706H_SEL_DSP2_FMTA_MASK 0x000031
88 #define SAA7706H_SEL_DSP2_SRCB_MASK 0x0001c0
89 #define SAA7706H_SEL_DSP2_FMTB_MASK 0x000e00
90 #define SAA7706H_SEL_DSP1_SRC_MASK 0x003000
91 #define SAA7706H_SEL_DSP1_FMT_MASK 0x01c003
92 #define SAA7706H_SEL_SPDIF2 0x020000
93 #define SAA7706H_SEL_HOST_IO_FMT_MASK 0x1c0000
94 #define SAA7706H_SEL_EN_HOST_IO 0x200000
96 #define SAA7706H_REG_IAC 0x1ff8
97 #define SAA7706H_REG_CLK_SET 0x1ff9
98 #define SAA7706H_REG_CLK_COEFF 0x1ffa
99 #define SAA7706H_REG_INPUT_SENS 0x1ffb
100 #define SAA7706H_INPUT_SENS_RDS_VOL_MASK 0x0003f
101 #define SAA7706H_INPUT_SENS_FM_VOL_MASK 0x00fc0
102 #define SAA7706H_INPUT_SENS_FM_MPX 0x01000
103 #define SAA7706H_INPUT_SENS_OFF_FILTER_A_EN 0x02000
104 #define SAA7706H_INPUT_SENS_OFF_FILTER_B_EN 0x04000
105 #define SAA7706H_REG_PHONE_NAV_AUDIO 0x1ffc
106 #define SAA7706H_REG_IO_CONF_DSP2 0x1ffd
107 #define SAA7706H_REG_STATUS_DSP2 0x1ffe
108 #define SAA7706H_REG_PC_DSP2 0x1fff
110 #define SAA7706H_DSP1_MOD0 0x0800
111 #define SAA7706H_DSP1_ROM_VER 0x097f
112 #define SAA7706H_DSP2_MPTR0 0x1000
114 #define SAA7706H_DSP1_MODPNTR 0x0000
116 #define SAA7706H_DSP2_XMEM_CONTLLCW 0x113e
117 #define SAA7706H_DSP2_XMEM_BUSAMP 0x114a
118 #define SAA7706H_DSP2_XMEM_FDACPNTR 0x11f9
119 #define SAA7706H_DSP2_XMEM_IIS1PNTR 0x11fb
121 #define SAA7706H_DSP2_YMEM_PVGA 0x212a
122 #define SAA7706H_DSP2_YMEM_PVAT1 0x212b
123 #define SAA7706H_DSP2_YMEM_PVAT 0x212c
124 #define SAA7706H_DSP2_YMEM_ROM_VER 0x21ff
126 #define SUPPORTED_DSP1_ROM_VER 0x667
143 return err > 0 ? -
EIO :
err;
146 static int saa7706h_i2c_transfer(
struct i2c_client *client,
152 return err > 0 ? -
EIO :
err;
157 struct i2c_client *client = v4l2_get_subdevdata(sd);
161 buf[pos++] = reg >> 8;
163 buf[pos++] = val >> 16;
164 buf[pos++] = val >> 8;
167 return saa7706h_i2c_send(client, buf, pos);
173 return *err ? *err : saa7706h_set_reg24(sd, reg, val);
178 struct i2c_client *client = v4l2_get_subdevdata(sd);
182 buf[pos++] = reg >> 8;
184 buf[pos++] = val >> 8;
187 return saa7706h_i2c_send(client, buf, pos);
193 return *err ? *err : saa7706h_set_reg16(sd, reg, val);
198 struct i2c_client *client = v4l2_get_subdevdata(sd);
201 u8 regaddr[] = {reg >> 8, reg};
204 .addr = client->
addr,
205 .len =
sizeof(regaddr),
209 .addr = client->
addr,
216 err = saa7706h_i2c_transfer(client, msg,
ARRAY_SIZE(msg));
220 return buf[0] << 8 | buf[1];
346 return saa7706h_mute(sd);
347 return saa7706h_unmute(sd);
352 static int saa7706h_g_chip_ident(
struct v4l2_subdev *sd,
355 struct i2c_client *client = v4l2_get_subdevdata(sd);
361 .g_chip_ident = saa7706h_g_chip_ident,
362 .queryctrl = saa7706h_queryctrl,
363 .g_ctrl = saa7706h_g_ctrl,
364 .s_ctrl = saa7706h_s_ctrl,
368 .core = &saa7706h_core_ops,
387 v4l_info(client,
"chip found @ 0x%02x (%s)\n",
401 v4l2_warn(sd,
"Unknown DSP1 ROM code version: 0x%x\n", err);
406 err = saa7706h_mute(sd);
423 struct v4l2_subdev *sd = i2c_get_clientdata(client);
443 .probe = saa7706h_probe,
445 .id_table = saa7706h_id,