Commit | Line | Data |
---|---|---|
c942fddf | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
4c66c920 MK |
2 | /* |
3 | * mxl111sf-gpio.c - driver for the MaxLinear MXL111SF | |
4 | * | |
08e10972 | 5 | * Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org> |
4c66c920 MK |
6 | */ |
7 | ||
8 | #include "mxl111sf-gpio.h" | |
9 | #include "mxl111sf-i2c.h" | |
10 | #include "mxl111sf.h" | |
11 | ||
12 | /* ------------------------------------------------------------------------- */ | |
13 | ||
14 | #define MXL_GPIO_MUX_REG_0 0x84 | |
15 | #define MXL_GPIO_MUX_REG_1 0x89 | |
16 | #define MXL_GPIO_MUX_REG_2 0x82 | |
17 | ||
18 | #define MXL_GPIO_DIR_INPUT 0 | |
19 | #define MXL_GPIO_DIR_OUTPUT 1 | |
20 | ||
21 | ||
22 | static int mxl111sf_set_gpo_state(struct mxl111sf_state *state, u8 pin, u8 val) | |
23 | { | |
24 | int ret; | |
25 | u8 tmp; | |
26 | ||
27 | mxl_debug_adv("(%d, %d)", pin, val); | |
28 | ||
29 | if ((pin > 0) && (pin < 8)) { | |
30 | ret = mxl111sf_read_reg(state, 0x19, &tmp); | |
31 | if (mxl_fail(ret)) | |
32 | goto fail; | |
33 | tmp &= ~(1 << (pin - 1)); | |
34 | tmp |= (val << (pin - 1)); | |
35 | ret = mxl111sf_write_reg(state, 0x19, tmp); | |
36 | if (mxl_fail(ret)) | |
37 | goto fail; | |
38 | } else if (pin <= 10) { | |
39 | if (pin == 0) | |
40 | pin += 7; | |
41 | ret = mxl111sf_read_reg(state, 0x30, &tmp); | |
42 | if (mxl_fail(ret)) | |
43 | goto fail; | |
44 | tmp &= ~(1 << (pin - 3)); | |
45 | tmp |= (val << (pin - 3)); | |
46 | ret = mxl111sf_write_reg(state, 0x30, tmp); | |
47 | if (mxl_fail(ret)) | |
48 | goto fail; | |
49 | } else | |
50 | ret = -EINVAL; | |
51 | fail: | |
52 | return ret; | |
53 | } | |
54 | ||
55 | static int mxl111sf_get_gpi_state(struct mxl111sf_state *state, u8 pin, u8 *val) | |
56 | { | |
57 | int ret; | |
58 | u8 tmp; | |
59 | ||
60 | mxl_debug("(0x%02x)", pin); | |
61 | ||
62 | *val = 0; | |
63 | ||
64 | switch (pin) { | |
65 | case 0: | |
66 | case 1: | |
67 | case 2: | |
68 | case 3: | |
69 | ret = mxl111sf_read_reg(state, 0x23, &tmp); | |
70 | if (mxl_fail(ret)) | |
71 | goto fail; | |
72 | *val = (tmp >> (pin + 4)) & 0x01; | |
73 | break; | |
74 | case 4: | |
75 | case 5: | |
76 | case 6: | |
77 | case 7: | |
78 | ret = mxl111sf_read_reg(state, 0x2f, &tmp); | |
79 | if (mxl_fail(ret)) | |
80 | goto fail; | |
81 | *val = (tmp >> pin) & 0x01; | |
82 | break; | |
83 | case 8: | |
84 | case 9: | |
85 | case 10: | |
86 | ret = mxl111sf_read_reg(state, 0x22, &tmp); | |
87 | if (mxl_fail(ret)) | |
88 | goto fail; | |
89 | *val = (tmp >> (pin - 3)) & 0x01; | |
90 | break; | |
91 | default: | |
92 | return -EINVAL; /* invalid pin */ | |
93 | } | |
94 | fail: | |
95 | return ret; | |
96 | } | |
97 | ||
98 | struct mxl_gpio_cfg { | |
99 | u8 pin; | |
100 | u8 dir; | |
101 | u8 val; | |
102 | }; | |
103 | ||
104 | static int mxl111sf_config_gpio_pins(struct mxl111sf_state *state, | |
105 | struct mxl_gpio_cfg *gpio_cfg) | |
106 | { | |
107 | int ret; | |
108 | u8 tmp; | |
109 | ||
110 | mxl_debug_adv("(%d, %d)", gpio_cfg->pin, gpio_cfg->dir); | |
111 | ||
112 | switch (gpio_cfg->pin) { | |
113 | case 0: | |
114 | case 1: | |
115 | case 2: | |
116 | case 3: | |
117 | ret = mxl111sf_read_reg(state, MXL_GPIO_MUX_REG_0, &tmp); | |
118 | if (mxl_fail(ret)) | |
119 | goto fail; | |
120 | tmp &= ~(1 << (gpio_cfg->pin + 4)); | |
121 | tmp |= (gpio_cfg->dir << (gpio_cfg->pin + 4)); | |
122 | ret = mxl111sf_write_reg(state, MXL_GPIO_MUX_REG_0, tmp); | |
123 | if (mxl_fail(ret)) | |
124 | goto fail; | |
125 | break; | |
126 | case 4: | |
127 | case 5: | |
128 | case 6: | |
129 | case 7: | |
130 | ret = mxl111sf_read_reg(state, MXL_GPIO_MUX_REG_1, &tmp); | |
131 | if (mxl_fail(ret)) | |
132 | goto fail; | |
133 | tmp &= ~(1 << gpio_cfg->pin); | |
134 | tmp |= (gpio_cfg->dir << gpio_cfg->pin); | |
135 | ret = mxl111sf_write_reg(state, MXL_GPIO_MUX_REG_1, tmp); | |
136 | if (mxl_fail(ret)) | |
137 | goto fail; | |
138 | break; | |
139 | case 8: | |
140 | case 9: | |
141 | case 10: | |
142 | ret = mxl111sf_read_reg(state, MXL_GPIO_MUX_REG_2, &tmp); | |
143 | if (mxl_fail(ret)) | |
144 | goto fail; | |
145 | tmp &= ~(1 << (gpio_cfg->pin - 3)); | |
146 | tmp |= (gpio_cfg->dir << (gpio_cfg->pin - 3)); | |
147 | ret = mxl111sf_write_reg(state, MXL_GPIO_MUX_REG_2, tmp); | |
148 | if (mxl_fail(ret)) | |
149 | goto fail; | |
150 | break; | |
151 | default: | |
152 | return -EINVAL; /* invalid pin */ | |
153 | } | |
154 | ||
155 | ret = (MXL_GPIO_DIR_OUTPUT == gpio_cfg->dir) ? | |
156 | mxl111sf_set_gpo_state(state, | |
157 | gpio_cfg->pin, gpio_cfg->val) : | |
158 | mxl111sf_get_gpi_state(state, | |
159 | gpio_cfg->pin, &gpio_cfg->val); | |
160 | mxl_fail(ret); | |
161 | fail: | |
162 | return ret; | |
163 | } | |
164 | ||
165 | static int mxl111sf_hw_do_set_gpio(struct mxl111sf_state *state, | |
166 | int gpio, int direction, int val) | |
167 | { | |
168 | struct mxl_gpio_cfg gpio_config = { | |
169 | .pin = gpio, | |
170 | .dir = direction, | |
171 | .val = val, | |
172 | }; | |
173 | ||
174 | mxl_debug("(%d, %d, %d)", gpio, direction, val); | |
175 | ||
176 | return mxl111sf_config_gpio_pins(state, &gpio_config); | |
177 | } | |
178 | ||
179 | /* ------------------------------------------------------------------------- */ | |
180 | ||
181 | #define PIN_MUX_MPEG_MODE_MASK 0x40 /* 0x17 <6> */ | |
182 | #define PIN_MUX_MPEG_PAR_EN_MASK 0x01 /* 0x18 <0> */ | |
183 | #define PIN_MUX_MPEG_SER_EN_MASK 0x02 /* 0x18 <1> */ | |
184 | #define PIN_MUX_MPG_IN_MUX_MASK 0x80 /* 0x3D <7> */ | |
185 | #define PIN_MUX_BT656_ENABLE_MASK 0x04 /* 0x12 <2> */ | |
186 | #define PIN_MUX_I2S_ENABLE_MASK 0x40 /* 0x15 <6> */ | |
187 | #define PIN_MUX_SPI_MODE_MASK 0x10 /* 0x3D <4> */ | |
188 | #define PIN_MUX_MCLK_EN_CTRL_MASK 0x10 /* 0x82 <4> */ | |
189 | #define PIN_MUX_MPSYN_EN_CTRL_MASK 0x20 /* 0x82 <5> */ | |
190 | #define PIN_MUX_MDVAL_EN_CTRL_MASK 0x40 /* 0x82 <6> */ | |
191 | #define PIN_MUX_MPERR_EN_CTRL_MASK 0x80 /* 0x82 <7> */ | |
192 | #define PIN_MUX_MDAT_EN_0_MASK 0x10 /* 0x84 <4> */ | |
193 | #define PIN_MUX_MDAT_EN_1_MASK 0x20 /* 0x84 <5> */ | |
194 | #define PIN_MUX_MDAT_EN_2_MASK 0x40 /* 0x84 <6> */ | |
195 | #define PIN_MUX_MDAT_EN_3_MASK 0x80 /* 0x84 <7> */ | |
196 | #define PIN_MUX_MDAT_EN_4_MASK 0x10 /* 0x89 <4> */ | |
197 | #define PIN_MUX_MDAT_EN_5_MASK 0x20 /* 0x89 <5> */ | |
198 | #define PIN_MUX_MDAT_EN_6_MASK 0x40 /* 0x89 <6> */ | |
199 | #define PIN_MUX_MDAT_EN_7_MASK 0x80 /* 0x89 <7> */ | |
200 | ||
201 | int mxl111sf_config_pin_mux_modes(struct mxl111sf_state *state, | |
202 | enum mxl111sf_mux_config pin_mux_config) | |
203 | { | |
204 | u8 r12, r15, r17, r18, r3D, r82, r84, r89; | |
205 | int ret; | |
206 | ||
207 | mxl_debug("(%d)", pin_mux_config); | |
208 | ||
209 | ret = mxl111sf_read_reg(state, 0x17, &r17); | |
210 | if (mxl_fail(ret)) | |
211 | goto fail; | |
212 | ret = mxl111sf_read_reg(state, 0x18, &r18); | |
213 | if (mxl_fail(ret)) | |
214 | goto fail; | |
215 | ret = mxl111sf_read_reg(state, 0x12, &r12); | |
216 | if (mxl_fail(ret)) | |
217 | goto fail; | |
218 | ret = mxl111sf_read_reg(state, 0x15, &r15); | |
219 | if (mxl_fail(ret)) | |
220 | goto fail; | |
221 | ret = mxl111sf_read_reg(state, 0x82, &r82); | |
222 | if (mxl_fail(ret)) | |
223 | goto fail; | |
224 | ret = mxl111sf_read_reg(state, 0x84, &r84); | |
225 | if (mxl_fail(ret)) | |
226 | goto fail; | |
227 | ret = mxl111sf_read_reg(state, 0x89, &r89); | |
228 | if (mxl_fail(ret)) | |
229 | goto fail; | |
230 | ret = mxl111sf_read_reg(state, 0x3D, &r3D); | |
231 | if (mxl_fail(ret)) | |
232 | goto fail; | |
233 | ||
234 | switch (pin_mux_config) { | |
235 | case PIN_MUX_TS_OUT_PARALLEL: | |
236 | /* mpeg_mode = 1 */ | |
237 | r17 |= PIN_MUX_MPEG_MODE_MASK; | |
238 | /* mpeg_par_en = 1 */ | |
239 | r18 |= PIN_MUX_MPEG_PAR_EN_MASK; | |
240 | /* mpeg_ser_en = 0 */ | |
241 | r18 &= ~PIN_MUX_MPEG_SER_EN_MASK; | |
242 | /* mpg_in_mux = 0 */ | |
243 | r3D &= ~PIN_MUX_MPG_IN_MUX_MASK; | |
244 | /* bt656_enable = 0 */ | |
245 | r12 &= ~PIN_MUX_BT656_ENABLE_MASK; | |
246 | /* i2s_enable = 0 */ | |
247 | r15 &= ~PIN_MUX_I2S_ENABLE_MASK; | |
248 | /* spi_mode = 0 */ | |
249 | r3D &= ~PIN_MUX_SPI_MODE_MASK; | |
250 | /* mclk_en_ctrl = 1 */ | |
251 | r82 |= PIN_MUX_MCLK_EN_CTRL_MASK; | |
252 | /* mperr_en_ctrl = 1 */ | |
253 | r82 |= PIN_MUX_MPERR_EN_CTRL_MASK; | |
254 | /* mdval_en_ctrl = 1 */ | |
255 | r82 |= PIN_MUX_MDVAL_EN_CTRL_MASK; | |
256 | /* mpsyn_en_ctrl = 1 */ | |
257 | r82 |= PIN_MUX_MPSYN_EN_CTRL_MASK; | |
258 | /* mdat_en_ctrl[3:0] = 0xF */ | |
259 | r84 |= 0xF0; | |
260 | /* mdat_en_ctrl[7:4] = 0xF */ | |
261 | r89 |= 0xF0; | |
262 | break; | |
263 | case PIN_MUX_TS_OUT_SERIAL: | |
264 | /* mpeg_mode = 1 */ | |
265 | r17 |= PIN_MUX_MPEG_MODE_MASK; | |
266 | /* mpeg_par_en = 0 */ | |
267 | r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK; | |
268 | /* mpeg_ser_en = 1 */ | |
269 | r18 |= PIN_MUX_MPEG_SER_EN_MASK; | |
270 | /* mpg_in_mux = 0 */ | |
271 | r3D &= ~PIN_MUX_MPG_IN_MUX_MASK; | |
272 | /* bt656_enable = 0 */ | |
273 | r12 &= ~PIN_MUX_BT656_ENABLE_MASK; | |
274 | /* i2s_enable = 0 */ | |
275 | r15 &= ~PIN_MUX_I2S_ENABLE_MASK; | |
276 | /* spi_mode = 0 */ | |
277 | r3D &= ~PIN_MUX_SPI_MODE_MASK; | |
278 | /* mclk_en_ctrl = 1 */ | |
279 | r82 |= PIN_MUX_MCLK_EN_CTRL_MASK; | |
280 | /* mperr_en_ctrl = 1 */ | |
281 | r82 |= PIN_MUX_MPERR_EN_CTRL_MASK; | |
282 | /* mdval_en_ctrl = 1 */ | |
283 | r82 |= PIN_MUX_MDVAL_EN_CTRL_MASK; | |
284 | /* mpsyn_en_ctrl = 1 */ | |
285 | r82 |= PIN_MUX_MPSYN_EN_CTRL_MASK; | |
286 | /* mdat_en_ctrl[3:0] = 0xF */ | |
287 | r84 |= 0xF0; | |
288 | /* mdat_en_ctrl[7:4] = 0xF */ | |
289 | r89 |= 0xF0; | |
290 | break; | |
291 | case PIN_MUX_GPIO_MODE: | |
292 | /* mpeg_mode = 0 */ | |
293 | r17 &= ~PIN_MUX_MPEG_MODE_MASK; | |
294 | /* mpeg_par_en = 0 */ | |
295 | r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK; | |
296 | /* mpeg_ser_en = 0 */ | |
297 | r18 &= ~PIN_MUX_MPEG_SER_EN_MASK; | |
298 | /* mpg_in_mux = 0 */ | |
299 | r3D &= ~PIN_MUX_MPG_IN_MUX_MASK; | |
300 | /* bt656_enable = 0 */ | |
301 | r12 &= ~PIN_MUX_BT656_ENABLE_MASK; | |
302 | /* i2s_enable = 0 */ | |
303 | r15 &= ~PIN_MUX_I2S_ENABLE_MASK; | |
304 | /* spi_mode = 0 */ | |
305 | r3D &= ~PIN_MUX_SPI_MODE_MASK; | |
306 | /* mclk_en_ctrl = 0 */ | |
307 | r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK; | |
308 | /* mperr_en_ctrl = 0 */ | |
309 | r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK; | |
310 | /* mdval_en_ctrl = 0 */ | |
311 | r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK; | |
312 | /* mpsyn_en_ctrl = 0 */ | |
313 | r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK; | |
314 | /* mdat_en_ctrl[3:0] = 0x0 */ | |
315 | r84 &= 0x0F; | |
316 | /* mdat_en_ctrl[7:4] = 0x0 */ | |
317 | r89 &= 0x0F; | |
318 | break; | |
319 | case PIN_MUX_TS_SERIAL_IN_MODE_0: | |
320 | /* mpeg_mode = 0 */ | |
321 | r17 &= ~PIN_MUX_MPEG_MODE_MASK; | |
322 | /* mpeg_par_en = 0 */ | |
323 | r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK; | |
324 | /* mpeg_ser_en = 1 */ | |
325 | r18 |= PIN_MUX_MPEG_SER_EN_MASK; | |
326 | /* mpg_in_mux = 0 */ | |
327 | r3D &= ~PIN_MUX_MPG_IN_MUX_MASK; | |
328 | /* bt656_enable = 0 */ | |
329 | r12 &= ~PIN_MUX_BT656_ENABLE_MASK; | |
330 | /* i2s_enable = 0 */ | |
331 | r15 &= ~PIN_MUX_I2S_ENABLE_MASK; | |
332 | /* spi_mode = 0 */ | |
333 | r3D &= ~PIN_MUX_SPI_MODE_MASK; | |
334 | /* mclk_en_ctrl = 0 */ | |
335 | r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK; | |
336 | /* mperr_en_ctrl = 0 */ | |
337 | r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK; | |
338 | /* mdval_en_ctrl = 0 */ | |
339 | r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK; | |
340 | /* mpsyn_en_ctrl = 0 */ | |
341 | r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK; | |
342 | /* mdat_en_ctrl[3:0] = 0x0 */ | |
343 | r84 &= 0x0F; | |
344 | /* mdat_en_ctrl[7:4] = 0x0 */ | |
345 | r89 &= 0x0F; | |
346 | break; | |
347 | case PIN_MUX_TS_SERIAL_IN_MODE_1: | |
348 | /* mpeg_mode = 0 */ | |
349 | r17 &= ~PIN_MUX_MPEG_MODE_MASK; | |
350 | /* mpeg_par_en = 0 */ | |
351 | r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK; | |
352 | /* mpeg_ser_en = 1 */ | |
353 | r18 |= PIN_MUX_MPEG_SER_EN_MASK; | |
354 | /* mpg_in_mux = 1 */ | |
355 | r3D |= PIN_MUX_MPG_IN_MUX_MASK; | |
356 | /* bt656_enable = 0 */ | |
357 | r12 &= ~PIN_MUX_BT656_ENABLE_MASK; | |
358 | /* i2s_enable = 0 */ | |
359 | r15 &= ~PIN_MUX_I2S_ENABLE_MASK; | |
360 | /* spi_mode = 0 */ | |
361 | r3D &= ~PIN_MUX_SPI_MODE_MASK; | |
362 | /* mclk_en_ctrl = 0 */ | |
363 | r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK; | |
364 | /* mperr_en_ctrl = 0 */ | |
365 | r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK; | |
366 | /* mdval_en_ctrl = 0 */ | |
367 | r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK; | |
368 | /* mpsyn_en_ctrl = 0 */ | |
369 | r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK; | |
370 | /* mdat_en_ctrl[3:0] = 0x0 */ | |
371 | r84 &= 0x0F; | |
372 | /* mdat_en_ctrl[7:4] = 0x0 */ | |
373 | r89 &= 0x0F; | |
374 | break; | |
375 | case PIN_MUX_TS_SPI_IN_MODE_1: | |
376 | /* mpeg_mode = 0 */ | |
377 | r17 &= ~PIN_MUX_MPEG_MODE_MASK; | |
378 | /* mpeg_par_en = 0 */ | |
379 | r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK; | |
380 | /* mpeg_ser_en = 1 */ | |
381 | r18 |= PIN_MUX_MPEG_SER_EN_MASK; | |
382 | /* mpg_in_mux = 1 */ | |
383 | r3D |= PIN_MUX_MPG_IN_MUX_MASK; | |
384 | /* bt656_enable = 0 */ | |
385 | r12 &= ~PIN_MUX_BT656_ENABLE_MASK; | |
386 | /* i2s_enable = 1 */ | |
387 | r15 |= PIN_MUX_I2S_ENABLE_MASK; | |
388 | /* spi_mode = 1 */ | |
389 | r3D |= PIN_MUX_SPI_MODE_MASK; | |
390 | /* mclk_en_ctrl = 0 */ | |
391 | r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK; | |
392 | /* mperr_en_ctrl = 0 */ | |
393 | r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK; | |
394 | /* mdval_en_ctrl = 0 */ | |
395 | r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK; | |
396 | /* mpsyn_en_ctrl = 0 */ | |
397 | r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK; | |
398 | /* mdat_en_ctrl[3:0] = 0x0 */ | |
399 | r84 &= 0x0F; | |
400 | /* mdat_en_ctrl[7:4] = 0x0 */ | |
401 | r89 &= 0x0F; | |
402 | break; | |
403 | case PIN_MUX_TS_SPI_IN_MODE_0: | |
404 | /* mpeg_mode = 0 */ | |
405 | r17 &= ~PIN_MUX_MPEG_MODE_MASK; | |
406 | /* mpeg_par_en = 0 */ | |
407 | r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK; | |
408 | /* mpeg_ser_en = 1 */ | |
409 | r18 |= PIN_MUX_MPEG_SER_EN_MASK; | |
410 | /* mpg_in_mux = 0 */ | |
411 | r3D &= ~PIN_MUX_MPG_IN_MUX_MASK; | |
412 | /* bt656_enable = 0 */ | |
413 | r12 &= ~PIN_MUX_BT656_ENABLE_MASK; | |
414 | /* i2s_enable = 1 */ | |
415 | r15 |= PIN_MUX_I2S_ENABLE_MASK; | |
416 | /* spi_mode = 1 */ | |
417 | r3D |= PIN_MUX_SPI_MODE_MASK; | |
418 | /* mclk_en_ctrl = 0 */ | |
419 | r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK; | |
420 | /* mperr_en_ctrl = 0 */ | |
421 | r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK; | |
422 | /* mdval_en_ctrl = 0 */ | |
423 | r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK; | |
424 | /* mpsyn_en_ctrl = 0 */ | |
425 | r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK; | |
426 | /* mdat_en_ctrl[3:0] = 0x0 */ | |
427 | r84 &= 0x0F; | |
428 | /* mdat_en_ctrl[7:4] = 0x0 */ | |
429 | r89 &= 0x0F; | |
430 | break; | |
431 | case PIN_MUX_TS_PARALLEL_IN: | |
432 | /* mpeg_mode = 0 */ | |
433 | r17 &= ~PIN_MUX_MPEG_MODE_MASK; | |
434 | /* mpeg_par_en = 1 */ | |
435 | r18 |= PIN_MUX_MPEG_PAR_EN_MASK; | |
436 | /* mpeg_ser_en = 0 */ | |
437 | r18 &= ~PIN_MUX_MPEG_SER_EN_MASK; | |
438 | /* mpg_in_mux = 0 */ | |
439 | r3D &= ~PIN_MUX_MPG_IN_MUX_MASK; | |
440 | /* bt656_enable = 0 */ | |
441 | r12 &= ~PIN_MUX_BT656_ENABLE_MASK; | |
442 | /* i2s_enable = 0 */ | |
443 | r15 &= ~PIN_MUX_I2S_ENABLE_MASK; | |
444 | /* spi_mode = 0 */ | |
445 | r3D &= ~PIN_MUX_SPI_MODE_MASK; | |
446 | /* mclk_en_ctrl = 0 */ | |
447 | r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK; | |
448 | /* mperr_en_ctrl = 0 */ | |
449 | r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK; | |
450 | /* mdval_en_ctrl = 0 */ | |
451 | r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK; | |
452 | /* mpsyn_en_ctrl = 0 */ | |
453 | r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK; | |
454 | /* mdat_en_ctrl[3:0] = 0x0 */ | |
455 | r84 &= 0x0F; | |
456 | /* mdat_en_ctrl[7:4] = 0x0 */ | |
457 | r89 &= 0x0F; | |
458 | break; | |
459 | case PIN_MUX_BT656_I2S_MODE: | |
460 | /* mpeg_mode = 0 */ | |
461 | r17 &= ~PIN_MUX_MPEG_MODE_MASK; | |
462 | /* mpeg_par_en = 0 */ | |
463 | r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK; | |
464 | /* mpeg_ser_en = 0 */ | |
465 | r18 &= ~PIN_MUX_MPEG_SER_EN_MASK; | |
466 | /* mpg_in_mux = 0 */ | |
467 | r3D &= ~PIN_MUX_MPG_IN_MUX_MASK; | |
468 | /* bt656_enable = 1 */ | |
469 | r12 |= PIN_MUX_BT656_ENABLE_MASK; | |
470 | /* i2s_enable = 1 */ | |
471 | r15 |= PIN_MUX_I2S_ENABLE_MASK; | |
472 | /* spi_mode = 0 */ | |
473 | r3D &= ~PIN_MUX_SPI_MODE_MASK; | |
474 | /* mclk_en_ctrl = 0 */ | |
475 | r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK; | |
476 | /* mperr_en_ctrl = 0 */ | |
477 | r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK; | |
478 | /* mdval_en_ctrl = 0 */ | |
479 | r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK; | |
480 | /* mpsyn_en_ctrl = 0 */ | |
481 | r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK; | |
482 | /* mdat_en_ctrl[3:0] = 0x0 */ | |
483 | r84 &= 0x0F; | |
484 | /* mdat_en_ctrl[7:4] = 0x0 */ | |
485 | r89 &= 0x0F; | |
486 | break; | |
487 | case PIN_MUX_DEFAULT: | |
488 | default: | |
489 | /* mpeg_mode = 1 */ | |
490 | r17 |= PIN_MUX_MPEG_MODE_MASK; | |
491 | /* mpeg_par_en = 0 */ | |
492 | r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK; | |
493 | /* mpeg_ser_en = 0 */ | |
494 | r18 &= ~PIN_MUX_MPEG_SER_EN_MASK; | |
495 | /* mpg_in_mux = 0 */ | |
496 | r3D &= ~PIN_MUX_MPG_IN_MUX_MASK; | |
497 | /* bt656_enable = 0 */ | |
498 | r12 &= ~PIN_MUX_BT656_ENABLE_MASK; | |
499 | /* i2s_enable = 0 */ | |
500 | r15 &= ~PIN_MUX_I2S_ENABLE_MASK; | |
501 | /* spi_mode = 0 */ | |
502 | r3D &= ~PIN_MUX_SPI_MODE_MASK; | |
503 | /* mclk_en_ctrl = 0 */ | |
504 | r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK; | |
505 | /* mperr_en_ctrl = 0 */ | |
506 | r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK; | |
507 | /* mdval_en_ctrl = 0 */ | |
508 | r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK; | |
509 | /* mpsyn_en_ctrl = 0 */ | |
510 | r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK; | |
511 | /* mdat_en_ctrl[3:0] = 0x0 */ | |
512 | r84 &= 0x0F; | |
513 | /* mdat_en_ctrl[7:4] = 0x0 */ | |
514 | r89 &= 0x0F; | |
515 | break; | |
516 | } | |
517 | ||
518 | ret = mxl111sf_write_reg(state, 0x17, r17); | |
519 | if (mxl_fail(ret)) | |
520 | goto fail; | |
521 | ret = mxl111sf_write_reg(state, 0x18, r18); | |
522 | if (mxl_fail(ret)) | |
523 | goto fail; | |
524 | ret = mxl111sf_write_reg(state, 0x12, r12); | |
525 | if (mxl_fail(ret)) | |
526 | goto fail; | |
527 | ret = mxl111sf_write_reg(state, 0x15, r15); | |
528 | if (mxl_fail(ret)) | |
529 | goto fail; | |
530 | ret = mxl111sf_write_reg(state, 0x82, r82); | |
531 | if (mxl_fail(ret)) | |
532 | goto fail; | |
533 | ret = mxl111sf_write_reg(state, 0x84, r84); | |
534 | if (mxl_fail(ret)) | |
535 | goto fail; | |
536 | ret = mxl111sf_write_reg(state, 0x89, r89); | |
537 | if (mxl_fail(ret)) | |
538 | goto fail; | |
539 | ret = mxl111sf_write_reg(state, 0x3D, r3D); | |
540 | if (mxl_fail(ret)) | |
541 | goto fail; | |
542 | fail: | |
543 | return ret; | |
544 | } | |
545 | ||
546 | /* ------------------------------------------------------------------------- */ | |
547 | ||
548 | static int mxl111sf_hw_set_gpio(struct mxl111sf_state *state, int gpio, int val) | |
549 | { | |
550 | return mxl111sf_hw_do_set_gpio(state, gpio, MXL_GPIO_DIR_OUTPUT, val); | |
551 | } | |
552 | ||
553 | static int mxl111sf_hw_gpio_initialize(struct mxl111sf_state *state) | |
554 | { | |
555 | u8 gpioval = 0x07; /* write protect enabled, signal LEDs off */ | |
556 | int i, ret; | |
557 | ||
558 | mxl_debug("()"); | |
559 | ||
560 | for (i = 3; i < 8; i++) { | |
561 | ret = mxl111sf_hw_set_gpio(state, i, (gpioval >> i) & 0x01); | |
562 | if (mxl_fail(ret)) | |
563 | break; | |
564 | } | |
565 | ||
566 | return ret; | |
567 | } | |
568 | ||
569 | #define PCA9534_I2C_ADDR (0x40 >> 1) | |
570 | static int pca9534_set_gpio(struct mxl111sf_state *state, int gpio, int val) | |
571 | { | |
572 | u8 w[2] = { 1, 0 }; | |
573 | u8 r = 0; | |
574 | struct i2c_msg msg[] = { | |
575 | { .addr = PCA9534_I2C_ADDR, | |
576 | .flags = 0, .buf = w, .len = 1 }, | |
577 | { .addr = PCA9534_I2C_ADDR, | |
578 | .flags = I2C_M_RD, .buf = &r, .len = 1 }, | |
579 | }; | |
580 | ||
581 | mxl_debug("(%d, %d)", gpio, val); | |
582 | ||
583 | /* read current GPIO levels from flip-flop */ | |
584 | i2c_transfer(&state->d->i2c_adap, msg, 2); | |
585 | ||
586 | /* prepare write buffer with current GPIO levels */ | |
587 | msg[0].len = 2; | |
588 | #if 0 | |
589 | w[0] = 1; | |
590 | #endif | |
591 | w[1] = r; | |
592 | ||
593 | /* clear the desired GPIO */ | |
594 | w[1] &= ~(1 << gpio); | |
595 | ||
596 | /* set the desired GPIO value */ | |
597 | w[1] |= ((val ? 1 : 0) << gpio); | |
598 | ||
599 | /* write new GPIO levels to flip-flop */ | |
600 | i2c_transfer(&state->d->i2c_adap, &msg[0], 1); | |
601 | ||
602 | return 0; | |
603 | } | |
604 | ||
605 | static int pca9534_init_port_expander(struct mxl111sf_state *state) | |
606 | { | |
607 | u8 w[2] = { 1, 0x07 }; /* write protect enabled, signal LEDs off */ | |
608 | ||
609 | struct i2c_msg msg = { | |
610 | .addr = PCA9534_I2C_ADDR, | |
611 | .flags = 0, .buf = w, .len = 2 | |
612 | }; | |
613 | ||
614 | mxl_debug("()"); | |
615 | ||
616 | i2c_transfer(&state->d->i2c_adap, &msg, 1); | |
617 | ||
618 | /* configure all pins as outputs */ | |
619 | w[0] = 3; | |
620 | w[1] = 0; | |
621 | ||
622 | i2c_transfer(&state->d->i2c_adap, &msg, 1); | |
623 | ||
624 | return 0; | |
625 | } | |
626 | ||
627 | int mxl111sf_set_gpio(struct mxl111sf_state *state, int gpio, int val) | |
628 | { | |
629 | mxl_debug("(%d, %d)", gpio, val); | |
630 | ||
631 | switch (state->gpio_port_expander) { | |
632 | default: | |
633 | mxl_printk(KERN_ERR, | |
634 | "gpio_port_expander undefined, assuming PCA9534"); | |
635 | /* fall-thru */ | |
636 | case mxl111sf_PCA9534: | |
637 | return pca9534_set_gpio(state, gpio, val); | |
638 | case mxl111sf_gpio_hw: | |
639 | return mxl111sf_hw_set_gpio(state, gpio, val); | |
640 | } | |
641 | } | |
642 | ||
643 | static int mxl111sf_probe_port_expander(struct mxl111sf_state *state) | |
644 | { | |
645 | int ret; | |
646 | u8 w = 1; | |
647 | u8 r = 0; | |
648 | struct i2c_msg msg[] = { | |
649 | { .flags = 0, .buf = &w, .len = 1 }, | |
650 | { .flags = I2C_M_RD, .buf = &r, .len = 1 }, | |
651 | }; | |
652 | ||
653 | mxl_debug("()"); | |
654 | ||
655 | msg[0].addr = 0x70 >> 1; | |
656 | msg[1].addr = 0x70 >> 1; | |
657 | ||
658 | /* read current GPIO levels from flip-flop */ | |
659 | ret = i2c_transfer(&state->d->i2c_adap, msg, 2); | |
660 | if (ret == 2) { | |
661 | state->port_expander_addr = msg[0].addr; | |
662 | state->gpio_port_expander = mxl111sf_PCA9534; | |
663 | mxl_debug("found port expander at 0x%02x", | |
664 | state->port_expander_addr); | |
665 | return 0; | |
666 | } | |
667 | ||
668 | msg[0].addr = 0x40 >> 1; | |
669 | msg[1].addr = 0x40 >> 1; | |
670 | ||
671 | ret = i2c_transfer(&state->d->i2c_adap, msg, 2); | |
672 | if (ret == 2) { | |
673 | state->port_expander_addr = msg[0].addr; | |
674 | state->gpio_port_expander = mxl111sf_PCA9534; | |
675 | mxl_debug("found port expander at 0x%02x", | |
676 | state->port_expander_addr); | |
677 | return 0; | |
678 | } | |
679 | state->port_expander_addr = 0xff; | |
680 | state->gpio_port_expander = mxl111sf_gpio_hw; | |
681 | mxl_debug("using hardware gpio"); | |
682 | return 0; | |
683 | } | |
684 | ||
685 | int mxl111sf_init_port_expander(struct mxl111sf_state *state) | |
686 | { | |
687 | mxl_debug("()"); | |
688 | ||
689 | if (0x00 == state->port_expander_addr) | |
690 | mxl111sf_probe_port_expander(state); | |
691 | ||
692 | switch (state->gpio_port_expander) { | |
693 | default: | |
694 | mxl_printk(KERN_ERR, | |
695 | "gpio_port_expander undefined, assuming PCA9534"); | |
696 | /* fall-thru */ | |
697 | case mxl111sf_PCA9534: | |
698 | return pca9534_init_port_expander(state); | |
699 | case mxl111sf_gpio_hw: | |
700 | return mxl111sf_hw_gpio_initialize(state); | |
701 | } | |
702 | } | |
703 | ||
704 | /* ------------------------------------------------------------------------ */ | |
705 | ||
706 | int mxl111sf_gpio_mode_switch(struct mxl111sf_state *state, unsigned int mode) | |
707 | { | |
708 | /* GPO: | |
709 | * 3 - ATSC/MH# | 1 = ATSC transport, 0 = MH transport | default 0 | |
710 | * 4 - ATSC_RST## | 1 = ATSC enable, 0 = ATSC Reset | default 0 | |
711 | * 5 - ATSC_EN | 1 = ATSC power enable, 0 = ATSC power off | default 0 | |
712 | * 6 - MH_RESET# | 1 = MH enable, 0 = MH Reset | default 0 | |
713 | * 7 - MH_EN | 1 = MH power enable, 0 = MH power off | default 0 | |
714 | */ | |
715 | mxl_debug("(%d)", mode); | |
716 | ||
717 | switch (mode) { | |
718 | case MXL111SF_GPIO_MOD_MH: | |
719 | mxl111sf_set_gpio(state, 4, 0); | |
720 | mxl111sf_set_gpio(state, 5, 0); | |
721 | msleep(50); | |
722 | mxl111sf_set_gpio(state, 7, 1); | |
723 | msleep(50); | |
724 | mxl111sf_set_gpio(state, 6, 1); | |
725 | msleep(50); | |
726 | ||
727 | mxl111sf_set_gpio(state, 3, 0); | |
728 | break; | |
729 | case MXL111SF_GPIO_MOD_ATSC: | |
730 | mxl111sf_set_gpio(state, 6, 0); | |
731 | mxl111sf_set_gpio(state, 7, 0); | |
732 | msleep(50); | |
733 | mxl111sf_set_gpio(state, 5, 1); | |
734 | msleep(50); | |
735 | mxl111sf_set_gpio(state, 4, 1); | |
736 | msleep(50); | |
737 | mxl111sf_set_gpio(state, 3, 1); | |
738 | break; | |
739 | default: /* DVBT / STANDBY */ | |
740 | mxl111sf_init_port_expander(state); | |
741 | break; | |
742 | } | |
743 | return 0; | |
744 | } |