Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mxl111sf-phy.c
Go to the documentation of this file.
1 /*
2  * mxl111sf-phy.c - driver for the MaxLinear MXL111SF
3  *
4  * Copyright (C) 2010 Michael Krufky <[email protected]>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20 
21 #include "mxl111sf-phy.h"
22 #include "mxl111sf-reg.h"
23 
25 {
26  struct mxl111sf_reg_ctrl_info mxl_111_overwrite_default[] = {
27  {0x07, 0xff, 0x0c},
28  {0x58, 0xff, 0x9d},
29  {0x09, 0xff, 0x00},
30  {0x06, 0xff, 0x06},
31  {0xc8, 0xff, 0x40}, /* ED_LE_WIN_OLD = 0 */
32  {0x8d, 0x01, 0x01}, /* NEGATE_Q */
33  {0x32, 0xff, 0xac}, /* DIG_RFREFSELECT = 12 */
34  {0x42, 0xff, 0x43}, /* DIG_REG_AMP = 4 */
35  {0x74, 0xff, 0xc4}, /* SSPUR_FS_PRIO = 4 */
36  {0x71, 0xff, 0xe6}, /* SPUR_ROT_PRIO_VAL = 1 */
37  {0x83, 0xff, 0x64}, /* INF_FILT1_THD_SC = 100 */
38  {0x85, 0xff, 0x64}, /* INF_FILT2_THD_SC = 100 */
39  {0x88, 0xff, 0xf0}, /* INF_THD = 240 */
40  {0x6f, 0xf0, 0xb0}, /* DFE_DLY = 11 */
41  {0x00, 0xff, 0x01}, /* Change to page 1 */
42  {0x81, 0xff, 0x11}, /* DSM_FERR_BYPASS = 1 */
43  {0xf4, 0xff, 0x07}, /* DIG_FREQ_CORR = 1 */
44  {0xd4, 0x1f, 0x0f}, /* SPUR_TEST_NOISE_TH = 15 */
45  {0xd6, 0xff, 0x0c}, /* SPUR_TEST_NOISE_PAPR = 12 */
46  {0x00, 0xff, 0x00}, /* Change to page 0 */
47  {0, 0, 0}
48  };
49 
50  mxl_debug("()");
51 
52  return mxl111sf_ctrl_program_regs(state, mxl_111_overwrite_default);
53 }
54 
56 {
57  int ret;
58  mxl_debug("()");
59 
60  ret = mxl111sf_write_reg(state, 0xff, 0x00); /* AIC */
61  if (mxl_fail(ret))
62  goto fail;
63  ret = mxl111sf_write_reg(state, 0x02, 0x01); /* get out of reset */
64  mxl_fail(ret);
65 fail:
66  return ret;
67 }
68 
70 {
71  int ret;
72 
73  mxl_debug("(%s)", MXL_SOC_MODE == mode ?
74  "MXL_SOC_MODE" : "MXL_TUNER_MODE");
75 
76  /* set device mode */
77  ret = mxl111sf_write_reg(state, 0x03,
78  MXL_SOC_MODE == mode ? 0x01 : 0x00);
79  if (mxl_fail(ret))
80  goto fail;
81 
82  ret = mxl111sf_write_reg_mask(state,
83  0x7d, 0x40, MXL_SOC_MODE == mode ?
84  0x00 : /* enable impulse noise filter,
85  INF_BYP = 0 */
86  0x40); /* disable impulse noise filter,
87  INF_BYP = 1 */
88  if (mxl_fail(ret))
89  goto fail;
90 
91  state->device_mode = mode;
92 fail:
93  return ret;
94 }
95 
96 /* power up tuner */
98 {
99  mxl_debug("(%d)", onoff);
100 
101  return mxl111sf_write_reg(state, 0x01, onoff ? 0x01 : 0x00);
102 }
103 
105 {
106  mxl_debug("()");
107 
108  return mxl111sf_write_reg_mask(state, 0x12, 0x04, 0x00);
109 }
110 
112 {
113  mxl_debug("()");
114 
115  return mxl111sf_write_reg_mask(state, 0x17, 0x40, 0x00);
116 }
117 
118 /* initialize TSIF as input port of MxL1X1SF for MPEG2 data transfer */
120  unsigned int parallel_serial,
121  unsigned int msb_lsb_1st,
122  unsigned int clock_phase,
123  unsigned int mpeg_valid_pol,
124  unsigned int mpeg_sync_pol)
125 {
126  int ret;
127  u8 mode, tmp;
128 
129  mxl_debug("(%u,%u,%u,%u,%u)", parallel_serial, msb_lsb_1st,
130  clock_phase, mpeg_valid_pol, mpeg_sync_pol);
131 
132  /* Enable PIN MUX */
134  mxl_fail(ret);
135 
136  /* Configure MPEG Clock phase */
138 
139  if (clock_phase == TSIF_NORMAL)
140  mode &= ~V6_INVERTED_CLK_PHASE;
141  else
142  mode |= V6_INVERTED_CLK_PHASE;
143 
144  ret = mxl111sf_write_reg(state, V6_MPEG_IN_CLK_INV_REG, mode);
145  mxl_fail(ret);
146 
147  /* Configure data input mode, MPEG Valid polarity, MPEG Sync polarity
148  * Get current configuration */
149  ret = mxl111sf_read_reg(state, V6_MPEG_IN_CTRL_REG, &mode);
150  mxl_fail(ret);
151 
152  /* Data Input mode */
153  if (parallel_serial == TSIF_INPUT_PARALLEL) {
154  /* Disable serial mode */
155  mode &= ~V6_MPEG_IN_DATA_SERIAL;
156 
157  /* Enable Parallel mode */
158  mode |= V6_MPEG_IN_DATA_PARALLEL;
159  } else {
160  /* Disable Parallel mode */
161  mode &= ~V6_MPEG_IN_DATA_PARALLEL;
162 
163  /* Enable Serial Mode */
164  mode |= V6_MPEG_IN_DATA_SERIAL;
165 
166  /* If serial interface is chosen, configure
167  MSB or LSB order in transmission */
168  ret = mxl111sf_read_reg(state,
170  &tmp);
171  mxl_fail(ret);
172 
173  if (msb_lsb_1st == MPEG_SER_MSB_FIRST_ENABLED)
174  tmp |= V6_MPEG_SER_MSB_FIRST;
175  else
176  tmp &= ~V6_MPEG_SER_MSB_FIRST;
177 
178  ret = mxl111sf_write_reg(state,
180  tmp);
181  mxl_fail(ret);
182  }
183 
184  /* MPEG Sync polarity */
185  if (mpeg_sync_pol == TSIF_NORMAL)
186  mode &= ~V6_INVERTED_MPEG_SYNC;
187  else
188  mode |= V6_INVERTED_MPEG_SYNC;
189 
190  /* MPEG Valid polarity */
191  if (mpeg_valid_pol == 0)
192  mode &= ~V6_INVERTED_MPEG_VALID;
193  else
194  mode |= V6_INVERTED_MPEG_VALID;
195 
196  ret = mxl111sf_write_reg(state, V6_MPEG_IN_CTRL_REG, mode);
197  mxl_fail(ret);
198 
199  return ret;
200 }
201 
203 {
204  static struct mxl111sf_reg_ctrl_info init_i2s[] = {
205  {0x1b, 0xff, 0x1e}, /* pin mux mode, Choose 656/I2S input */
206  {0x15, 0x60, 0x60}, /* Enable I2S */
207  {0x17, 0xe0, 0x20}, /* Input, MPEG MODE USB,
208  Inverted 656 Clock, I2S_SOFT_RESET,
209  0 : Normal operation, 1 : Reset State */
210 #if 0
211  {0x12, 0x01, 0x00}, /* AUDIO_IRQ_CLR (Overflow Indicator) */
212 #endif
213  {0x00, 0xff, 0x02}, /* Change to Control Page */
214  {0x26, 0x0d, 0x0d}, /* I2S_MODE & BT656_SRC_SEL for FPGA only */
215  {0x00, 0xff, 0x00},
216  {0, 0, 0}
217  };
218  int ret;
219 
220  mxl_debug("(0x%02x)", sample_size);
221 
222  ret = mxl111sf_ctrl_program_regs(state, init_i2s);
223  if (mxl_fail(ret))
224  goto fail;
225 
226  ret = mxl111sf_write_reg(state, V6_I2S_NUM_SAMPLES_REG, sample_size);
227  mxl_fail(ret);
228 fail:
229  return ret;
230 }
231 
233 {
234  static struct mxl111sf_reg_ctrl_info disable_i2s[] = {
235  {0x15, 0x40, 0x00},
236  {0, 0, 0}
237  };
238 
239  mxl_debug("()");
240 
241  return mxl111sf_ctrl_program_regs(state, disable_i2s);
242 }
243 
245  u8 msb_start_pos, u8 data_width)
246 {
247  int ret;
248  u8 tmp;
249 
250  mxl_debug("(0x%02x, 0x%02x)", msb_start_pos, data_width);
251 
253  if (mxl_fail(ret))
254  goto fail;
255 
256  tmp &= 0xe0;
257  tmp |= msb_start_pos;
259  if (mxl_fail(ret))
260  goto fail;
261 
262  ret = mxl111sf_read_reg(state, V6_I2S_STREAM_END_BIT_REG, &tmp);
263  if (mxl_fail(ret))
264  goto fail;
265 
266  tmp &= 0xe0;
267  tmp |= data_width;
269  mxl_fail(ret);
270 fail:
271  return ret;
272 }
273 
275 {
276  u8 val;
277  int ret;
278 
279  mxl_debug("(%d)", onoff);
280 
281  ret = mxl111sf_write_reg(state, 0x00, 0x02);
282  if (mxl_fail(ret))
283  goto fail;
284 
285  ret = mxl111sf_read_reg(state, V8_SPI_MODE_REG, &val);
286  if (mxl_fail(ret))
287  goto fail;
288 
289  if (onoff)
290  val |= 0x04;
291  else
292  val &= ~0x04;
293 
294  ret = mxl111sf_write_reg(state, V8_SPI_MODE_REG, val);
295  if (mxl_fail(ret))
296  goto fail;
297 
298  ret = mxl111sf_write_reg(state, 0x00, 0x00);
299  mxl_fail(ret);
300 fail:
301  return ret;
302 }
303 
305  u8 control_mode, u8 current_setting,
306  u8 current_value, u8 hysteresis_value)
307 {
308  int ret;
309  u8 val;
310  /* current value will be set for both automatic & manual IDAC control */
311  val = current_value;
312 
313  if (control_mode == IDAC_MANUAL_CONTROL) {
314  /* enable manual control of IDAC */
316 
317  if (current_setting == IDAC_CURRENT_SINKING_ENABLE)
318  /* enable current sinking in manual mode */
320  else
321  /* disable current sinking in manual mode */
323  } else {
324  /* disable manual control of IDAC */
326 
327  /* set hysteresis value reg: 0x0B<5:0> */
329  (hysteresis_value & 0x3F));
330  mxl_fail(ret);
331  }
332 
333  ret = mxl111sf_write_reg(state, V6_IDAC_SETTINGS_REG, val);
334  mxl_fail(ret);
335 
336  return ret;
337 }
338 
339 /*
340  * Local variables:
341  * c-basic-offset: 8
342  * End:
343  */