aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx18/cx18-firmware.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/cx18/cx18-firmware.c')
-rw-r--r--drivers/media/video/cx18/cx18-firmware.c196
1 files changed, 90 insertions, 106 deletions
diff --git a/drivers/media/video/cx18/cx18-firmware.c b/drivers/media/video/cx18/cx18-firmware.c
index 2694ce350631..51534428cd00 100644
--- a/drivers/media/video/cx18/cx18-firmware.c
+++ b/drivers/media/video/cx18/cx18-firmware.c
@@ -20,6 +20,7 @@
20 */ 20 */
21 21
22#include "cx18-driver.h" 22#include "cx18-driver.h"
23#include "cx18-io.h"
23#include "cx18-scb.h" 24#include "cx18-scb.h"
24#include "cx18-irq.h" 25#include "cx18-irq.h"
25#include "cx18-firmware.h" 26#include "cx18-firmware.h"
@@ -41,9 +42,6 @@
41 42
42#define CX18_REG_BUS_TIMEOUT_EN 0xc72024 43#define CX18_REG_BUS_TIMEOUT_EN 0xc72024
43 44
44#define CX18_AUDIO_ENABLE 0xc72014
45#define CX18_REG_BUS_TIMEOUT_EN 0xc72024
46
47#define CX18_FAST_CLOCK_PLL_INT 0xc78000 45#define CX18_FAST_CLOCK_PLL_INT 0xc78000
48#define CX18_FAST_CLOCK_PLL_FRAC 0xc78004 46#define CX18_FAST_CLOCK_PLL_FRAC 0xc78004
49#define CX18_FAST_CLOCK_PLL_POST 0xc78008 47#define CX18_FAST_CLOCK_PLL_POST 0xc78008
@@ -89,10 +87,6 @@
89 87
90#define CX18_DSP0_INTERRUPT_MASK 0xd0004C 88#define CX18_DSP0_INTERRUPT_MASK 0xd0004C
91 89
92/* Encoder/decoder firmware sizes */
93#define CX18_FW_CPU_SIZE (174716)
94#define CX18_FW_APU_SIZE (141200)
95
96#define APU_ROM_SYNC1 0x6D676553 /* "mgeS" */ 90#define APU_ROM_SYNC1 0x6D676553 /* "mgeS" */
97#define APU_ROM_SYNC2 0x72646548 /* "rdeH" */ 91#define APU_ROM_SYNC2 0x72646548 /* "rdeH" */
98 92
@@ -103,41 +97,28 @@ struct cx18_apu_rom_seghdr {
103 u32 size; 97 u32 size;
104}; 98};
105 99
106static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx, long size) 100static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx)
107{ 101{
108 const struct firmware *fw = NULL; 102 const struct firmware *fw = NULL;
109 int retries = 3;
110 int i, j; 103 int i, j;
104 unsigned size;
111 u32 __iomem *dst = (u32 __iomem *)mem; 105 u32 __iomem *dst = (u32 __iomem *)mem;
112 const u32 *src; 106 const u32 *src;
113 107
114retry: 108 if (request_firmware(&fw, fn, &cx->dev->dev)) {
115 if (!retries || request_firmware(&fw, fn, &cx->dev->dev)) { 109 CX18_ERR("Unable to open firmware %s\n", fn);
116 CX18_ERR("Unable to open firmware %s (must be %ld bytes)\n",
117 fn, size);
118 CX18_ERR("Did you put the firmware in the hotplug firmware directory?\n"); 110 CX18_ERR("Did you put the firmware in the hotplug firmware directory?\n");
119 return -ENOMEM; 111 return -ENOMEM;
120 } 112 }
121 113
122 src = (const u32 *)fw->data; 114 src = (const u32 *)fw->data;
123 115
124 if (fw->size != size) {
125 /* Due to race conditions in firmware loading (esp. with
126 udev <0.95) the wrong file was sometimes loaded. So we check
127 filesizes to see if at least the right-sized file was
128 loaded. If not, then we retry. */
129 CX18_INFO("retry: file loaded was not %s (expected size %ld, got %zd)\n",
130 fn, size, fw->size);
131 release_firmware(fw);
132 retries--;
133 goto retry;
134 }
135 for (i = 0; i < fw->size; i += 4096) { 116 for (i = 0; i < fw->size; i += 4096) {
136 setup_page(i); 117 cx18_setup_page(cx, i);
137 for (j = i; j < fw->size && j < i + 4096; j += 4) { 118 for (j = i; j < fw->size && j < i + 4096; j += 4) {
138 /* no need for endianness conversion on the ppc */ 119 /* no need for endianness conversion on the ppc */
139 __raw_writel(*src, dst); 120 cx18_raw_writel(cx, *src, dst);
140 if (__raw_readl(dst) != *src) { 121 if (cx18_raw_readl(cx, dst) != *src) {
141 CX18_ERR("Mismatch at offset %x\n", i); 122 CX18_ERR("Mismatch at offset %x\n", i);
142 release_firmware(fw); 123 release_firmware(fw);
143 return -EIO; 124 return -EIO;
@@ -148,15 +129,16 @@ retry:
148 } 129 }
149 if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags)) 130 if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags))
150 CX18_INFO("loaded %s firmware (%zd bytes)\n", fn, fw->size); 131 CX18_INFO("loaded %s firmware (%zd bytes)\n", fn, fw->size);
132 size = fw->size;
151 release_firmware(fw); 133 release_firmware(fw);
152 return size; 134 return size;
153} 135}
154 136
155static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx, long size) 137static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx)
156{ 138{
157 const struct firmware *fw = NULL; 139 const struct firmware *fw = NULL;
158 int retries = 3;
159 int i, j; 140 int i, j;
141 unsigned size;
160 const u32 *src; 142 const u32 *src;
161 struct cx18_apu_rom_seghdr seghdr; 143 struct cx18_apu_rom_seghdr seghdr;
162 const u8 *vers; 144 const u8 *vers;
@@ -164,10 +146,8 @@ static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx,
164 u32 apu_version = 0; 146 u32 apu_version = 0;
165 int sz; 147 int sz;
166 148
167retry: 149 if (request_firmware(&fw, fn, &cx->dev->dev)) {
168 if (!retries || request_firmware(&fw, fn, &cx->dev->dev)) { 150 CX18_ERR("unable to open firmware %s\n", fn);
169 CX18_ERR("unable to open firmware %s (must be %ld bytes)\n",
170 fn, size);
171 CX18_ERR("did you put the firmware in the hotplug firmware directory?\n"); 151 CX18_ERR("did you put the firmware in the hotplug firmware directory?\n");
172 return -ENOMEM; 152 return -ENOMEM;
173 } 153 }
@@ -176,19 +156,8 @@ retry:
176 vers = fw->data + sizeof(seghdr); 156 vers = fw->data + sizeof(seghdr);
177 sz = fw->size; 157 sz = fw->size;
178 158
179 if (fw->size != size) {
180 /* Due to race conditions in firmware loading (esp. with
181 udev <0.95) the wrong file was sometimes loaded. So we check
182 filesizes to see if at least the right-sized file was
183 loaded. If not, then we retry. */
184 CX18_INFO("retry: file loaded was not %s (expected size %ld, got %zd)\n",
185 fn, size, fw->size);
186 release_firmware(fw);
187 retries--;
188 goto retry;
189 }
190 apu_version = (vers[0] << 24) | (vers[4] << 16) | vers[32]; 159 apu_version = (vers[0] << 24) | (vers[4] << 16) | vers[32];
191 while (offset + sizeof(seghdr) < size) { 160 while (offset + sizeof(seghdr) < fw->size) {
192 /* TODO: byteswapping */ 161 /* TODO: byteswapping */
193 memcpy(&seghdr, src + offset / 4, sizeof(seghdr)); 162 memcpy(&seghdr, src + offset / 4, sizeof(seghdr));
194 offset += sizeof(seghdr); 163 offset += sizeof(seghdr);
@@ -202,12 +171,15 @@ retry:
202 if (offset + seghdr.size > sz) 171 if (offset + seghdr.size > sz)
203 break; 172 break;
204 for (i = 0; i < seghdr.size; i += 4096) { 173 for (i = 0; i < seghdr.size; i += 4096) {
205 setup_page(offset + i); 174 cx18_setup_page(cx, offset + i);
206 for (j = i; j < seghdr.size && j < i + 4096; j += 4) { 175 for (j = i; j < seghdr.size && j < i + 4096; j += 4) {
207 /* no need for endianness conversion on the ppc */ 176 /* no need for endianness conversion on the ppc */
208 __raw_writel(src[(offset + j) / 4], dst + seghdr.addr + j); 177 cx18_raw_writel(cx, src[(offset + j) / 4],
209 if (__raw_readl(dst + seghdr.addr + j) != src[(offset + j) / 4]) { 178 dst + seghdr.addr + j);
210 CX18_ERR("Mismatch at offset %x\n", offset + j); 179 if (cx18_raw_readl(cx, dst + seghdr.addr + j)
180 != src[(offset + j) / 4]) {
181 CX18_ERR("Mismatch at offset %x\n",
182 offset + j);
211 release_firmware(fw); 183 release_firmware(fw);
212 return -EIO; 184 return -EIO;
213 } 185 }
@@ -218,45 +190,48 @@ retry:
218 if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags)) 190 if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags))
219 CX18_INFO("loaded %s firmware V%08x (%zd bytes)\n", 191 CX18_INFO("loaded %s firmware V%08x (%zd bytes)\n",
220 fn, apu_version, fw->size); 192 fn, apu_version, fw->size);
193 size = fw->size;
221 release_firmware(fw); 194 release_firmware(fw);
222 /* Clear bit0 for APU to start from 0 */ 195 /* Clear bit0 for APU to start from 0 */
223 write_reg(read_reg(0xc72030) & ~1, 0xc72030); 196 cx18_write_reg(cx, cx18_read_reg(cx, 0xc72030) & ~1, 0xc72030);
224 return size; 197 return size;
225} 198}
226 199
227void cx18_halt_firmware(struct cx18 *cx) 200void cx18_halt_firmware(struct cx18 *cx)
228{ 201{
229 CX18_DEBUG_INFO("Preparing for firmware halt.\n"); 202 CX18_DEBUG_INFO("Preparing for firmware halt.\n");
230 write_reg(0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */ 203 cx18_write_reg(cx, 0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */
231 write_reg(0x00020002, CX18_ADEC_CONTROL); 204 cx18_write_reg(cx, 0x00020002, CX18_ADEC_CONTROL);
232} 205}
233 206
234void cx18_init_power(struct cx18 *cx, int lowpwr) 207void cx18_init_power(struct cx18 *cx, int lowpwr)
235{ 208{
236 /* power-down Spare and AOM PLLs */ 209 /* power-down Spare and AOM PLLs */
237 /* power-up fast, slow and mpeg PLLs */ 210 /* power-up fast, slow and mpeg PLLs */
238 write_reg(0x00000008, CX18_PLL_POWER_DOWN); 211 cx18_write_reg(cx, 0x00000008, CX18_PLL_POWER_DOWN);
239 212
240 /* ADEC out of sleep */ 213 /* ADEC out of sleep */
241 write_reg(0x00020000, CX18_ADEC_CONTROL); 214 cx18_write_reg(cx, 0x00020000, CX18_ADEC_CONTROL);
242 215
243 /* The fast clock is at 200/245 MHz */ 216 /* The fast clock is at 200/245 MHz */
244 write_reg(lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT); 217 cx18_write_reg(cx, lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT);
245 write_reg(lowpwr ? 0x1EFBF37 : 0x038E3D7, CX18_FAST_CLOCK_PLL_FRAC); 218 cx18_write_reg(cx, lowpwr ? 0x1EFBF37 : 0x038E3D7,
219 CX18_FAST_CLOCK_PLL_FRAC);
246 220
247 write_reg(2, CX18_FAST_CLOCK_PLL_POST); 221 cx18_write_reg(cx, 2, CX18_FAST_CLOCK_PLL_POST);
248 write_reg(1, CX18_FAST_CLOCK_PLL_PRESCALE); 222 cx18_write_reg(cx, 1, CX18_FAST_CLOCK_PLL_PRESCALE);
249 write_reg(4, CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH); 223 cx18_write_reg(cx, 4, CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH);
250 224
251 /* set slow clock to 125/120 MHz */ 225 /* set slow clock to 125/120 MHz */
252 write_reg(lowpwr ? 0x11 : 0x10, CX18_SLOW_CLOCK_PLL_INT); 226 cx18_write_reg(cx, lowpwr ? 0x11 : 0x10, CX18_SLOW_CLOCK_PLL_INT);
253 write_reg(lowpwr ? 0xEBAF05 : 0x18618A8, CX18_SLOW_CLOCK_PLL_FRAC); 227 cx18_write_reg(cx, lowpwr ? 0xEBAF05 : 0x18618A8,
254 write_reg(4, CX18_SLOW_CLOCK_PLL_POST); 228 CX18_SLOW_CLOCK_PLL_FRAC);
229 cx18_write_reg(cx, 4, CX18_SLOW_CLOCK_PLL_POST);
255 230
256 /* mpeg clock pll 54MHz */ 231 /* mpeg clock pll 54MHz */
257 write_reg(0xF, CX18_MPEG_CLOCK_PLL_INT); 232 cx18_write_reg(cx, 0xF, CX18_MPEG_CLOCK_PLL_INT);
258 write_reg(0x2BCFEF, CX18_MPEG_CLOCK_PLL_FRAC); 233 cx18_write_reg(cx, 0x2BCFEF, CX18_MPEG_CLOCK_PLL_FRAC);
259 write_reg(8, CX18_MPEG_CLOCK_PLL_POST); 234 cx18_write_reg(cx, 8, CX18_MPEG_CLOCK_PLL_POST);
260 235
261 /* Defaults */ 236 /* Defaults */
262 /* APU = SC or SC/2 = 125/62.5 */ 237 /* APU = SC or SC/2 = 125/62.5 */
@@ -273,88 +248,97 @@ void cx18_init_power(struct cx18 *cx, int lowpwr)
273 /* VFC = disabled */ 248 /* VFC = disabled */
274 /* USB = disabled */ 249 /* USB = disabled */
275 250
276 write_reg(lowpwr ? 0xFFFF0020 : 0x00060004, CX18_CLOCK_SELECT1); 251 cx18_write_reg(cx, lowpwr ? 0xFFFF0020 : 0x00060004,
277 write_reg(lowpwr ? 0xFFFF0004 : 0x00060006, CX18_CLOCK_SELECT2); 252 CX18_CLOCK_SELECT1);
253 cx18_write_reg(cx, lowpwr ? 0xFFFF0004 : 0x00060006,
254 CX18_CLOCK_SELECT2);
278 255
279 write_reg(0xFFFF0002, CX18_HALF_CLOCK_SELECT1); 256 cx18_write_reg(cx, 0xFFFF0002, CX18_HALF_CLOCK_SELECT1);
280 write_reg(0xFFFF0104, CX18_HALF_CLOCK_SELECT2); 257 cx18_write_reg(cx, 0xFFFF0104, CX18_HALF_CLOCK_SELECT2);
281 258
282 write_reg(0xFFFF9026, CX18_CLOCK_ENABLE1); 259 cx18_write_reg(cx, 0xFFFF9026, CX18_CLOCK_ENABLE1);
283 write_reg(0xFFFF3105, CX18_CLOCK_ENABLE2); 260 cx18_write_reg(cx, 0xFFFF3105, CX18_CLOCK_ENABLE2);
284} 261}
285 262
286void cx18_init_memory(struct cx18 *cx) 263void cx18_init_memory(struct cx18 *cx)
287{ 264{
288 cx18_msleep_timeout(10, 0); 265 cx18_msleep_timeout(10, 0);
289 write_reg(0x10000, CX18_DDR_SOFT_RESET); 266 cx18_write_reg(cx, 0x10000, CX18_DDR_SOFT_RESET);
290 cx18_msleep_timeout(10, 0); 267 cx18_msleep_timeout(10, 0);
291 268
292 write_reg(cx->card->ddr.chip_config, CX18_DDR_CHIP_CONFIG); 269 cx18_write_reg(cx, cx->card->ddr.chip_config, CX18_DDR_CHIP_CONFIG);
293 270
294 cx18_msleep_timeout(10, 0); 271 cx18_msleep_timeout(10, 0);
295 272
296 write_reg(cx->card->ddr.refresh, CX18_DDR_REFRESH); 273 cx18_write_reg(cx, cx->card->ddr.refresh, CX18_DDR_REFRESH);
297 write_reg(cx->card->ddr.timing1, CX18_DDR_TIMING1); 274 cx18_write_reg(cx, cx->card->ddr.timing1, CX18_DDR_TIMING1);
298 write_reg(cx->card->ddr.timing2, CX18_DDR_TIMING2); 275 cx18_write_reg(cx, cx->card->ddr.timing2, CX18_DDR_TIMING2);
299 276
300 cx18_msleep_timeout(10, 0); 277 cx18_msleep_timeout(10, 0);
301 278
302 /* Initialize DQS pad time */ 279 /* Initialize DQS pad time */
303 write_reg(cx->card->ddr.tune_lane, CX18_DDR_TUNE_LANE); 280 cx18_write_reg(cx, cx->card->ddr.tune_lane, CX18_DDR_TUNE_LANE);
304 write_reg(cx->card->ddr.initial_emrs, CX18_DDR_INITIAL_EMRS); 281 cx18_write_reg(cx, cx->card->ddr.initial_emrs, CX18_DDR_INITIAL_EMRS);
305 282
306 cx18_msleep_timeout(10, 0); 283 cx18_msleep_timeout(10, 0);
307 284
308 write_reg(0x20000, CX18_DDR_SOFT_RESET); 285 cx18_write_reg(cx, 0x20000, CX18_DDR_SOFT_RESET);
309 cx18_msleep_timeout(10, 0); 286 cx18_msleep_timeout(10, 0);
310 287
311 /* use power-down mode when idle */ 288 /* use power-down mode when idle */
312 write_reg(0x00000010, CX18_DDR_POWER_REG); 289 cx18_write_reg(cx, 0x00000010, CX18_DDR_POWER_REG);
313 290
314 write_reg(0x10001, CX18_REG_BUS_TIMEOUT_EN); 291 cx18_write_reg(cx, 0x10001, CX18_REG_BUS_TIMEOUT_EN);
315 292
316 write_reg(0x48, CX18_DDR_MB_PER_ROW_7); 293 cx18_write_reg(cx, 0x48, CX18_DDR_MB_PER_ROW_7);
317 write_reg(0xE0000, CX18_DDR_BASE_63_ADDR); 294 cx18_write_reg(cx, 0xE0000, CX18_DDR_BASE_63_ADDR);
318 295
319 write_reg(0x00000101, CX18_WMB_CLIENT02); /* AO */ 296 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT02); /* AO */
320 write_reg(0x00000101, CX18_WMB_CLIENT09); /* AI2 */ 297 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT09); /* AI2 */
321 write_reg(0x00000101, CX18_WMB_CLIENT05); /* VIM1 */ 298 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT05); /* VIM1 */
322 write_reg(0x00000101, CX18_WMB_CLIENT06); /* AI1 */ 299 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT06); /* AI1 */
323 write_reg(0x00000101, CX18_WMB_CLIENT07); /* 3D comb */ 300 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT07); /* 3D comb */
324 write_reg(0x00000101, CX18_WMB_CLIENT10); /* ME */ 301 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT10); /* ME */
325 write_reg(0x00000101, CX18_WMB_CLIENT12); /* ENC */ 302 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT12); /* ENC */
326 write_reg(0x00000101, CX18_WMB_CLIENT13); /* PK */ 303 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT13); /* PK */
327 write_reg(0x00000101, CX18_WMB_CLIENT11); /* RC */ 304 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT11); /* RC */
328 write_reg(0x00000101, CX18_WMB_CLIENT14); /* AVO */ 305 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT14); /* AVO */
329} 306}
330 307
331int cx18_firmware_init(struct cx18 *cx) 308int cx18_firmware_init(struct cx18 *cx)
332{ 309{
333 /* Allow chip to control CLKRUN */ 310 /* Allow chip to control CLKRUN */
334 write_reg(0x5, CX18_DSP0_INTERRUPT_MASK); 311 cx18_write_reg(cx, 0x5, CX18_DSP0_INTERRUPT_MASK);
335 312
336 write_reg(0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */ 313 cx18_write_reg(cx, 0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */
337 314
338 cx18_msleep_timeout(1, 0); 315 cx18_msleep_timeout(1, 0);
339 316
340 sw1_irq_enable(IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU); 317 cx18_sw1_irq_enable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
341 sw2_irq_enable(IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); 318 cx18_sw2_irq_enable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
342 319
343 /* Only if the processor is not running */ 320 /* Only if the processor is not running */
344 if (read_reg(CX18_PROC_SOFT_RESET) & 8) { 321 if (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 8) {
345 int sz = load_apu_fw_direct("v4l-cx23418-apu.fw", 322 int sz = load_apu_fw_direct("v4l-cx23418-apu.fw",
346 cx->enc_mem, cx, CX18_FW_APU_SIZE); 323 cx->enc_mem, cx);
324
325 cx18_write_enc(cx, 0xE51FF004, 0);
326 cx18_write_enc(cx, 0xa00000, 4); /* todo: not hardcoded */
327 /* Start APU */
328 cx18_write_reg(cx, 0x00010000, CX18_PROC_SOFT_RESET);
329 cx18_msleep_timeout(500, 0);
347 330
348 sz = sz <= 0 ? sz : load_cpu_fw_direct("v4l-cx23418-cpu.fw", 331 sz = sz <= 0 ? sz : load_cpu_fw_direct("v4l-cx23418-cpu.fw",
349 cx->enc_mem, cx, CX18_FW_CPU_SIZE); 332 cx->enc_mem, cx);
350 333
351 if (sz > 0) { 334 if (sz > 0) {
352 int retries = 0; 335 int retries = 0;
353 336
354 /* start the CPU */ 337 /* start the CPU */
355 write_reg(0x00080000, CX18_PROC_SOFT_RESET); 338 cx18_write_reg(cx, 0x00080000, CX18_PROC_SOFT_RESET);
356 while (retries++ < 50) { /* Loop for max 500mS */ 339 while (retries++ < 50) { /* Loop for max 500mS */
357 if ((read_reg(CX18_PROC_SOFT_RESET) & 1) == 0) 340 if ((cx18_read_reg(cx, CX18_PROC_SOFT_RESET)
341 & 1) == 0)
358 break; 342 break;
359 cx18_msleep_timeout(10, 0); 343 cx18_msleep_timeout(10, 0);
360 } 344 }
@@ -368,6 +352,6 @@ int cx18_firmware_init(struct cx18 *cx)
368 return -EIO; 352 return -EIO;
369 } 353 }
370 /* initialize GPIO */ 354 /* initialize GPIO */
371 write_reg(0x14001400, 0xC78110); 355 cx18_write_reg(cx, 0x14001400, 0xC78110);
372 return 0; 356 return 0;
373} 357}