1/* 2 * av7110_hw.c: av7110 low level hardware access and firmware interface 3 * 4 * Copyright (C) 1999-2002 Ralph Metzler 5 * & Marcus Metzler for convergence integrated media GmbH 6 * 7 * originally based on code by: 8 * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.de> 9 * 10 * This program is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU General Public License 12 * as published by the Free Software Foundation; either version 2 13 * of the License, or (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 23 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html 24 * 25 * the project's page is at http://www.linuxtv.org/ 26 */ 27 28/* for debugging ARM communication: */ 29//#define COM_DEBUG 30 31#include <stdarg.h> 32#include <linux/types.h> 33#include <linux/kernel.h> 34#include <linux/string.h> 35#include <linux/delay.h> 36#include <linux/fs.h> 37 38#include "av7110.h" 39#include "av7110_hw.h" 40 41#define _NOHANDSHAKE 42 43/**************************************************************************** 44 * DEBI functions 45 ****************************************************************************/ 46 47/* This DEBI code is based on the Stradis driver 48 by Nathan Laredo <laredo@gnu.org> */ 49 50int av7110_debiwrite(struct av7110 *av7110, u32 config, 51 int addr, u32 val, int count) 52{ 53 struct saa7146_dev *dev = av7110->dev; 54 55 if (count <= 0 || count > 32764) { 56 printk("%s: invalid count %d\n", __func__, count); 57 return -1; 58 } 59 if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) { 60 printk("%s: wait_for_debi_done failed\n", __func__); 61 return -1; 62 } 63 saa7146_write(dev, DEBI_CONFIG, config); 64 if (count <= 4) /* immediate transfer */ 65 saa7146_write(dev, DEBI_AD, val); 66 else /* block transfer */ 67 saa7146_write(dev, DEBI_AD, av7110->debi_bus); 68 saa7146_write(dev, DEBI_COMMAND, (count << 17) | (addr & 0xffff)); 69 saa7146_write(dev, MC2, (2 << 16) | 2); 70 return 0; 71} 72 73u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count) 74{ 75 struct saa7146_dev *dev = av7110->dev; 76 u32 result = 0; 77 78 if (count > 32764 || count <= 0) { 79 printk("%s: invalid count %d\n", __func__, count); 80 return 0; 81 } 82 if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) { 83 printk("%s: wait_for_debi_done #1 failed\n", __func__); 84 return 0; 85 } 86 saa7146_write(dev, DEBI_AD, av7110->debi_bus); 87 saa7146_write(dev, DEBI_COMMAND, (count << 17) | 0x10000 | (addr & 0xffff)); 88 89 saa7146_write(dev, DEBI_CONFIG, config); 90 saa7146_write(dev, MC2, (2 << 16) | 2); 91 if (count > 4) 92 return count; 93 if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) { 94 printk("%s: wait_for_debi_done #2 failed\n", __func__); 95 return 0; 96 } 97 98 result = saa7146_read(dev, DEBI_AD); 99 result &= (0xffffffffUL >> ((4 - count) * 8)); 100 return result; 101} 102 103 104 105/* av7110 ARM core boot stuff */ 106#if 0 107void av7110_reset_arm(struct av7110 *av7110) 108{ 109 saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTLO); 110 111 /* Disable DEBI and GPIO irq */ 112 SAA7146_IER_DISABLE(av7110->dev, MASK_19 | MASK_03); 113 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03); 114 115 saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTHI); 116 msleep(30); /* the firmware needs some time to initialize */ 117 118 ARM_ResetMailBox(av7110); 119 120 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03); 121 SAA7146_IER_ENABLE(av7110->dev, MASK_03); 122 123 av7110->arm_ready = 1; 124 dprintk(1, "reset ARM\n"); 125} 126#endif /* 0 */ 127 128static int waitdebi(struct av7110 *av7110, int adr, int state) 129{ 130 int k; 131 132 dprintk(4, "%p\n", av7110); 133 134 for (k = 0; k < 100; k++) { 135 if (irdebi(av7110, DEBINOSWAP, adr, 0, 2) == state) 136 return 0; 137 udelay(5); 138 } 139 return -ETIMEDOUT; 140} 141 142static int load_dram(struct av7110 *av7110, u32 *data, int len) 143{ 144 int i; 145 int blocks, rest; 146 u32 base, bootblock = AV7110_BOOT_BLOCK; 147 148 dprintk(4, "%p\n", av7110); 149 150 blocks = len / AV7110_BOOT_MAX_SIZE; 151 rest = len % AV7110_BOOT_MAX_SIZE; 152 base = DRAM_START_CODE; 153 154 for (i = 0; i < blocks; i++) { 155 if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) { 156 printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at block %d\n", i); 157 return -ETIMEDOUT; 158 } 159 dprintk(4, "writing DRAM block %d\n", i); 160 mwdebi(av7110, DEBISWAB, bootblock, 161 ((u8 *)data) + i * AV7110_BOOT_MAX_SIZE, AV7110_BOOT_MAX_SIZE); 162 bootblock ^= 0x1400; 163 iwdebi(av7110, DEBISWAB, AV7110_BOOT_BASE, swab32(base), 4); 164 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, AV7110_BOOT_MAX_SIZE, 2); 165 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2); 166 base += AV7110_BOOT_MAX_SIZE; 167 } 168 169 if (rest > 0) { 170 if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) { 171 printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at last block\n"); 172 return -ETIMEDOUT; 173 } 174 if (rest > 4) 175 mwdebi(av7110, DEBISWAB, bootblock, 176 ((u8 *)data) + i * AV7110_BOOT_MAX_SIZE, rest); 177 else 178 mwdebi(av7110, DEBISWAB, bootblock, 179 ((u8 *)data) + i * AV7110_BOOT_MAX_SIZE - 4, rest + 4); 180 181 iwdebi(av7110, DEBISWAB, AV7110_BOOT_BASE, swab32(base), 4); 182 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, rest, 2); 183 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2); 184 } 185 if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) { 186 printk(KERN_ERR "dvb-ttpci: load_dram(): timeout after last block\n"); 187 return -ETIMEDOUT; 188 } 189 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, 0, 2); 190 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2); 191 if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_AV7110_BOOT_COMPLETE) < 0) { 192 printk(KERN_ERR "dvb-ttpci: load_dram(): final handshake timeout\n"); 193 return -ETIMEDOUT; 194 } 195 return 0; 196} 197 198 199/* we cannot write av7110 DRAM directly, so load a bootloader into 200 * the DPRAM which implements a simple boot protocol */ 201int av7110_bootarm(struct av7110 *av7110) 202{ 203 const struct firmware *fw; 204 const char *fw_name = "av7110/bootcode.bin"; 205 struct saa7146_dev *dev = av7110->dev; 206 u32 ret; 207 int i; 208 209 dprintk(4, "%p\n", av7110); 210 211 av7110->arm_ready = 0; 212 213 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO); 214 215 /* Disable DEBI and GPIO irq */ 216 SAA7146_IER_DISABLE(av7110->dev, MASK_03 | MASK_19); 217 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03); 218 219 /* enable DEBI */ 220 saa7146_write(av7110->dev, MC1, 0x08800880); 221 saa7146_write(av7110->dev, DD1_STREAM_B, 0x00000000); 222 saa7146_write(av7110->dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26)); 223 224 /* test DEBI */ 225 iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4); 226 /* FIXME: Why does Nexus CA require 2x iwdebi for first init? */ 227 iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4); 228 229 if ((ret=irdebi(av7110, DEBINOSWAP, DPRAM_BASE, 0, 4)) != 0x10325476) { 230 printk(KERN_ERR "dvb-ttpci: debi test in av7110_bootarm() failed: " 231 "%08x != %08x (check your BIOS 'Plug&Play OS' settings)\n", 232 ret, 0x10325476); 233 return -1; 234 } 235 for (i = 0; i < 8192; i += 4) 236 iwdebi(av7110, DEBISWAP, DPRAM_BASE + i, 0x00, 4); 237 dprintk(2, "debi test OK\n"); 238 239 /* boot */ 240 dprintk(1, "load boot code\n"); 241 saa7146_setgpio(dev, ARM_IRQ_LINE, SAA7146_GPIO_IRQLO); 242 //saa7146_setgpio(dev, DEBI_DONE_LINE, SAA7146_GPIO_INPUT); 243 //saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT); 244 245 ret = request_firmware(&fw, fw_name, &dev->pci->dev); 246 if (ret) { 247 printk(KERN_ERR "dvb-ttpci: Failed to load firmware \"%s\"\n", 248 fw_name); 249 return ret; 250 } 251 252 mwdebi(av7110, DEBISWAB, DPRAM_BASE, fw->data, fw->size); 253 release_firmware(fw); 254 iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2); 255 256 if (saa7146_wait_for_debi_done(av7110->dev, 1)) { 257 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): " 258 "saa7146_wait_for_debi_done() timed out\n"); 259 return -ETIMEDOUT; 260 } 261 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI); 262 mdelay(1); 263 264 dprintk(1, "load dram code\n"); 265 if (load_dram(av7110, (u32 *)av7110->bin_root, av7110->size_root) < 0) { 266 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): " 267 "load_dram() failed\n"); 268 return -1; 269 } 270 271 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO); 272 mdelay(1); 273 274 dprintk(1, "load dpram code\n"); 275 mwdebi(av7110, DEBISWAB, DPRAM_BASE, av7110->bin_dpram, av7110->size_dpram); 276 277 if (saa7146_wait_for_debi_done(av7110->dev, 1)) { 278 printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): " 279 "saa7146_wait_for_debi_done() timed out after loading DRAM\n"); 280 return -ETIMEDOUT; 281 } 282 saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI); 283 msleep(30); /* the firmware needs some time to initialize */ 284 285 //ARM_ClearIrq(av7110); 286 ARM_ResetMailBox(av7110); 287 SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03); 288 SAA7146_IER_ENABLE(av7110->dev, MASK_03); 289 290 av7110->arm_errors = 0; 291 av7110->arm_ready = 1; 292 return 0; 293} 294MODULE_FIRMWARE("av7110/bootcode.bin"); 295 296/**************************************************************************** 297 * DEBI command polling 298 ****************************************************************************/ 299 300int av7110_wait_msgstate(struct av7110 *av7110, u16 flags) 301{ 302 unsigned long start; 303 u32 stat; 304 int err; 305 306 if (FW_VERSION(av7110->arm_app) <= 0x261c) { 307 /* not supported by old firmware */ 308 msleep(50); 309 return 0; 310 } 311 312 /* new firmware */ 313 start = jiffies; 314 for (;;) { 315 err = time_after(jiffies, start + ARM_WAIT_FREE); 316 if (mutex_lock_interruptible(&av7110->dcomlock)) 317 return -ERESTARTSYS; 318 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2); 319 mutex_unlock(&av7110->dcomlock); 320 if ((stat & flags) == 0) 321 break; 322 if (err) { 323 printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n", 324 __func__, stat & flags); 325 return -ETIMEDOUT; 326 } 327 msleep(1); 328 } 329 return 0; 330} 331 332static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) 333{ 334 int i; 335 unsigned long start; 336 char *type = NULL; 337 u16 flags[2] = {0, 0}; 338 u32 stat; 339 int err; 340 341// dprintk(4, "%p\n", av7110); 342 343 if (!av7110->arm_ready) { 344 dprintk(1, "arm not ready.\n"); 345 return -ENXIO; 346 } 347 348 start = jiffies; 349 while (1) { 350 err = time_after(jiffies, start + ARM_WAIT_FREE); 351 if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0) 352 break; 353 if (err) { 354 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __func__); 355 av7110->arm_errors++; 356 return -ETIMEDOUT; 357 } 358 msleep(1); 359 } 360 361 if (FW_VERSION(av7110->arm_app) <= 0x261f) 362 wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0xffff, 2); 363 364#ifndef _NOHANDSHAKE 365 start = jiffies; 366 while (1) { 367 err = time_after(jiffies, start + ARM_WAIT_SHAKE); 368 if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0) 369 break; 370 if (err) { 371 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __func__); 372 return -ETIMEDOUT; 373 } 374 msleep(1); 375 } 376#endif 377 378 switch ((buf[0] >> 8) & 0xff) { 379 case COMTYPE_PIDFILTER: 380 case COMTYPE_ENCODER: 381 case COMTYPE_REC_PLAY: 382 case COMTYPE_MPEGDECODER: 383 type = "MSG"; 384 flags[0] = GPMQOver; 385 flags[1] = GPMQFull; 386 break; 387 case COMTYPE_OSD: 388 type = "OSD"; 389 flags[0] = OSDQOver; 390 flags[1] = OSDQFull; 391 break; 392 case COMTYPE_MISC: 393 if (FW_VERSION(av7110->arm_app) >= 0x261d) { 394 type = "MSG"; 395 flags[0] = GPMQOver; 396 flags[1] = GPMQBusy; 397 } 398 break; 399 default: 400 break; 401 } 402 403 if (type != NULL) { 404 /* non-immediate COMMAND type */ 405 start = jiffies; 406 for (;;) { 407 err = time_after(jiffies, start + ARM_WAIT_FREE); 408 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2); 409 if (stat & flags[0]) { 410 printk(KERN_ERR "%s: %s QUEUE overflow\n", 411 __func__, type); 412 return -1; 413 } 414 if ((stat & flags[1]) == 0) 415 break; 416 if (err) { 417 printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n", 418 __func__, type); 419 av7110->arm_errors++; 420 return -ETIMEDOUT; 421 } 422 msleep(1); 423 } 424 } 425 426 for (i = 2; i < length; i++) 427 wdebi(av7110, DEBINOSWAP, COMMAND + 2 * i, (u32) buf[i], 2); 428 429 if (length) 430 wdebi(av7110, DEBINOSWAP, COMMAND + 2, (u32) buf[1], 2); 431 else 432 wdebi(av7110, DEBINOSWAP, COMMAND + 2, 0, 2); 433 434 wdebi(av7110, DEBINOSWAP, COMMAND, (u32) buf[0], 2); 435 436 if (FW_VERSION(av7110->arm_app) <= 0x261f) 437 wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0x0000, 2); 438 439#ifdef COM_DEBUG 440 start = jiffies; 441 while (1) { 442 err = time_after(jiffies, start + ARM_WAIT_FREE); 443 if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0) 444 break; 445 if (err) { 446 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n", 447 __func__, (buf[0] >> 8) & 0xff); 448 return -ETIMEDOUT; 449 } 450 msleep(1); 451 } 452 453 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2); 454 if (stat & GPMQOver) { 455 printk(KERN_ERR "dvb-ttpci: %s(): GPMQOver\n", __func__); 456 return -ENOSPC; 457 } 458 else if (stat & OSDQOver) { 459 printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __func__); 460 return -ENOSPC; 461 } 462#endif 463 464 return 0; 465} 466 467static int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) 468{ 469 int ret; 470 471// dprintk(4, "%p\n", av7110); 472 473 if (!av7110->arm_ready) { 474 dprintk(1, "arm not ready.\n"); 475 return -1; 476 } 477 if (mutex_lock_interruptible(&av7110->dcomlock)) 478 return -ERESTARTSYS; 479 480 ret = __av7110_send_fw_cmd(av7110, buf, length); 481 mutex_unlock(&av7110->dcomlock); 482 if (ret && ret!=-ERESTARTSYS) 483 printk(KERN_ERR "dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n", 484 __func__, ret); 485 return ret; 486} 487 488int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, ...) 489{ 490 va_list args; 491 u16 buf[num + 2]; 492 int i, ret; 493 494// dprintk(4, "%p\n", av7110); 495 496 buf[0] = ((type << 8) | com); 497 buf[1] = num; 498 499 if (num) { 500 va_start(args, num); 501 for (i = 0; i < num; i++) 502 buf[i + 2] = va_arg(args, u32); 503 va_end(args); 504 } 505 506 ret = av7110_send_fw_cmd(av7110, buf, num + 2); 507 if (ret && ret != -ERESTARTSYS) 508 printk(KERN_ERR "dvb-ttpci: av7110_fw_cmd error %d\n", ret); 509 return ret; 510} 511 512#if 0 513int av7110_send_ci_cmd(struct av7110 *av7110, u8 subcom, u8 *buf, u8 len) 514{ 515 int i, ret; 516 u16 cmd[18] = { ((COMTYPE_COMMON_IF << 8) + subcom), 517 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 518 519 dprintk(4, "%p\n", av7110); 520 521 for(i = 0; i < len && i < 32; i++) 522 { 523 if(i % 2 == 0) 524 cmd[(i / 2) + 2] = (u16)(buf[i]) << 8; 525 else 526 cmd[(i / 2) + 2] |= buf[i]; 527 } 528 529 ret = av7110_send_fw_cmd(av7110, cmd, 18); 530 if (ret && ret != -ERESTARTSYS) 531 printk(KERN_ERR "dvb-ttpci: av7110_send_ci_cmd error %d\n", ret); 532 return ret; 533} 534#endif /* 0 */ 535 536int av7110_fw_request(struct av7110 *av7110, u16 *request_buf, 537 int request_buf_len, u16 *reply_buf, int reply_buf_len) 538{ 539 int err; 540 s16 i; 541 unsigned long start; 542#ifdef COM_DEBUG 543 u32 stat; 544#endif 545 546 dprintk(4, "%p\n", av7110); 547 548 if (!av7110->arm_ready) { 549 dprintk(1, "arm not ready.\n"); 550 return -1; 551 } 552 553 if (mutex_lock_interruptible(&av7110->dcomlock)) 554 return -ERESTARTSYS; 555 556 if ((err = __av7110_send_fw_cmd(av7110, request_buf, request_buf_len)) < 0) { 557 mutex_unlock(&av7110->dcomlock); 558 printk(KERN_ERR "dvb-ttpci: av7110_fw_request error %d\n", err); 559 return err; 560 } 561 562 start = jiffies; 563 while (1) { 564 err = time_after(jiffies, start + ARM_WAIT_FREE); 565 if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0) 566 break; 567 if (err) { 568 printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __func__); 569 mutex_unlock(&av7110->dcomlock); 570 return -ETIMEDOUT; 571 } 572#ifdef _NOHANDSHAKE 573 msleep(1); 574#endif 575 } 576 577#ifndef _NOHANDSHAKE 578 start = jiffies; 579 while (1) { 580 err = time_after(jiffies, start + ARM_WAIT_SHAKE); 581 if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0) 582 break; 583 if (err) { 584 printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __func__); 585 mutex_unlock(&av7110->dcomlock); 586 return -ETIMEDOUT; 587 } 588 msleep(1); 589 } 590#endif 591 592#ifdef COM_DEBUG 593 stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2); 594 if (stat & GPMQOver) { 595 printk(KERN_ERR "%s: GPMQOver\n", __func__); 596 mutex_unlock(&av7110->dcomlock); 597 return -1; 598 } 599 else if (stat & OSDQOver) { 600 printk(KERN_ERR "%s: OSDQOver\n", __func__); 601 mutex_unlock(&av7110->dcomlock); 602 return -1; 603 } 604#endif 605 606 for (i = 0; i < reply_buf_len; i++) 607 reply_buf[i] = rdebi(av7110, DEBINOSWAP, COM_BUFF + 2 * i, 0, 2); 608 609 mutex_unlock(&av7110->dcomlock); 610 return 0; 611} 612 613static int av7110_fw_query(struct av7110 *av7110, u16 tag, u16* buf, s16 length) 614{ 615 int ret; 616 ret = av7110_fw_request(av7110, &tag, 0, buf, length); 617 if (ret) 618 printk(KERN_ERR "dvb-ttpci: av7110_fw_query error %d\n", ret); 619 return ret; 620} 621 622 623/**************************************************************************** 624 * Firmware commands 625 ****************************************************************************/ 626 627/* get version of the firmware ROM, RTSL, video ucode and ARM application */ 628int av7110_firmversion(struct av7110 *av7110) 629{ 630 u16 buf[20]; 631 u16 tag = ((COMTYPE_REQUEST << 8) + ReqVersion); 632 633 dprintk(4, "%p\n", av7110); 634 635 if (av7110_fw_query(av7110, tag, buf, 16)) { 636 printk("dvb-ttpci: failed to boot firmware @ card %d\n", 637 av7110->dvb_adapter.num); 638 return -EIO; 639 } 640 641 av7110->arm_fw = (buf[0] << 16) + buf[1]; 642 av7110->arm_rtsl = (buf[2] << 16) + buf[3]; 643 av7110->arm_vid = (buf[4] << 16) + buf[5]; 644 av7110->arm_app = (buf[6] << 16) + buf[7]; 645 av7110->avtype = (buf[8] << 16) + buf[9]; 646 647 printk("dvb-ttpci: info @ card %d: firm %08x, rtsl %08x, vid %08x, app %08x\n", 648 av7110->dvb_adapter.num, av7110->arm_fw, 649 av7110->arm_rtsl, av7110->arm_vid, av7110->arm_app); 650 651 /* print firmware capabilities */ 652 if (FW_CI_LL_SUPPORT(av7110->arm_app)) 653 printk("dvb-ttpci: firmware @ card %d supports CI link layer interface\n", 654 av7110->dvb_adapter.num); 655 else 656 printk("dvb-ttpci: no firmware support for CI link layer interface @ card %d\n", 657 av7110->dvb_adapter.num); 658 659 return 0; 660} 661 662 663int av7110_diseqc_send(struct av7110 *av7110, int len, u8 *msg, unsigned long burst) 664{ 665 int i, ret; 666 u16 buf[18] = { ((COMTYPE_AUDIODAC << 8) + SendDiSEqC), 667 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 668 669 dprintk(4, "%p\n", av7110); 670 671 if (len > 10) 672 len = 10; 673 674 buf[1] = len + 2; 675 buf[2] = len; 676 677 if (burst != -1) 678 buf[3] = burst ? 0x01 : 0x00; 679 else 680 buf[3] = 0xffff; 681 682 for (i = 0; i < len; i++) 683 buf[i + 4] = msg[i]; 684 685 ret = av7110_send_fw_cmd(av7110, buf, 18); 686 if (ret && ret!=-ERESTARTSYS) 687 printk(KERN_ERR "dvb-ttpci: av7110_diseqc_send error %d\n", ret); 688 return ret; 689} 690 691 692#ifdef CONFIG_DVB_AV7110_OSD 693 694static inline int SetColorBlend(struct av7110 *av7110, u8 windownr) 695{ 696 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetCBlend, 1, windownr); 697} 698 699static inline int SetBlend_(struct av7110 *av7110, u8 windownr, 700 enum av7110_osd_palette_type colordepth, u16 index, u8 blending) 701{ 702 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetBlend, 4, 703 windownr, colordepth, index, blending); 704} 705 706static inline int SetColor_(struct av7110 *av7110, u8 windownr, 707 enum av7110_osd_palette_type colordepth, u16 index, u16 colorhi, u16 colorlo) 708{ 709 return av7110_fw_cmd(av7110, COMTYPE_OSD, SetColor, 5, 710 windownr, colordepth, index, colorhi, colorlo); 711} 712 713static inline int SetFont(struct av7110 *av7110, u8 windownr, u8 fontsize, 714 u16 colorfg, u16 colorbg) 715{ 716 return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Font, 4, 717 windownr, fontsize, colorfg, colorbg); 718} 719 720static int FlushText(struct av7110 *av7110) 721{ 722 unsigned long start; 723 int err; 724 725 if (mutex_lock_interruptible(&av7110->dcomlock)) 726 return -ERESTARTSYS; 727 start = jiffies; 728 while (1) { 729 err = time_after(jiffies, start + ARM_WAIT_OSD); 730 if (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2) == 0) 731 break; 732 if (err) { 733 printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n", 734 __func__); 735 mutex_unlock(&av7110->dcomlock); 736 return -ETIMEDOUT; 737 } 738 msleep(1); 739 } 740 mutex_unlock(&av7110->dcomlock); 741 return 0; 742} 743 744static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, char *buf) 745{ 746 int i, ret; 747 unsigned long start; 748 int length = strlen(buf) + 1; 749 u16 cbuf[5] = { (COMTYPE_OSD << 8) + DText, 3, win, x, y }; 750 751 if (mutex_lock_interruptible(&av7110->dcomlock)) 752 return -ERESTARTSYS; 753 754 start = jiffies; 755 while (1) { 756 ret = time_after(jiffies, start + ARM_WAIT_OSD); 757 if (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2) == 0) 758 break; 759 if (ret) { 760 printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n", 761 __func__); 762 mutex_unlock(&av7110->dcomlock); 763 return -ETIMEDOUT; 764 } 765 msleep(1); 766 } 767#ifndef _NOHANDSHAKE 768 start = jiffies; 769 while (1) { 770 ret = time_after(jiffies, start + ARM_WAIT_SHAKE); 771 if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0) 772 break; 773 if (ret) { 774 printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n", 775 __func__); 776 mutex_unlock(&av7110->dcomlock); 777 return -ETIMEDOUT; 778 } 779 msleep(1); 780 } 781#endif 782 for (i = 0; i < length / 2; i++) 783 wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2, 784 swab16(*(u16 *)(buf + 2 * i)), 2); 785 if (length & 1) 786 wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2, 0, 2); 787 ret = __av7110_send_fw_cmd(av7110, cbuf, 5); 788 mutex_unlock(&av7110->dcomlock); 789 if (ret && ret!=-ERESTARTSYS) 790 printk(KERN_ERR "dvb-ttpci: WriteText error %d\n", ret); 791 return ret; 792} 793 794static inline int DrawLine(struct av7110 *av7110, u8 windownr, 795 u16 x, u16 y, u16 dx, u16 dy, u16 color) 796{ 797 return av7110_fw_cmd(av7110, COMTYPE_OSD, DLine, 6, 798 windownr, x, y, dx, dy, color); 799} 800 801static inline int DrawBlock(struct av7110 *av7110, u8 windownr, 802 u16 x, u16 y, u16 dx, u16 dy, u16 color) 803{ 804 return av7110_fw_cmd(av7110, COMTYPE_OSD, DBox, 6, 805 windownr, x, y, dx, dy, color); 806} 807 808static inline int HideWindow(struct av7110 *av7110, u8 windownr) 809{ 810 return av7110_fw_cmd(av7110, COMTYPE_OSD, WHide, 1, windownr); 811} 812 813static inline int MoveWindowRel(struct av7110 *av7110, u8 windownr, u16 x, u16 y) 814{ 815 return av7110_fw_cmd(av7110, COMTYPE_OSD, WMoveD, 3, windownr, x, y); 816} 817 818static inline int MoveWindowAbs(struct av7110 *av7110, u8 windownr, u16 x, u16 y) 819{ 820 return av7110_fw_cmd(av7110, COMTYPE_OSD, WMoveA, 3, windownr, x, y); 821} 822 823static inline int DestroyOSDWindow(struct av7110 *av7110, u8 windownr) 824{ 825 return av7110_fw_cmd(av7110, COMTYPE_OSD, WDestroy, 1, windownr); 826} 827 828static inline int CreateOSDWindow(struct av7110 *av7110, u8 windownr, 829 osd_raw_window_t disptype, 830 u16 width, u16 height) 831{ 832 return av7110_fw_cmd(av7110, COMTYPE_OSD, WCreate, 4, 833 windownr, disptype, width, height); 834} 835 836 837static enum av7110_osd_palette_type bpp2pal[8] = { 838 Pal1Bit, Pal2Bit, 0, Pal4Bit, 0, 0, 0, Pal8Bit 839}; 840static osd_raw_window_t bpp2bit[8] = { 841 OSD_BITMAP1, OSD_BITMAP2, 0, OSD_BITMAP4, 0, 0, 0, OSD_BITMAP8 842}; 843 844static inline int WaitUntilBmpLoaded(struct av7110 *av7110) 845{ 846 int ret = wait_event_timeout(av7110->bmpq, 847 av7110->bmp_state != BMP_LOADING, 10*HZ); 848 if (ret == 0) { 849 printk("dvb-ttpci: warning: timeout waiting in LoadBitmap: %d, %d\n", 850 ret, av7110->bmp_state); 851 av7110->bmp_state = BMP_NONE; 852 return -ETIMEDOUT; 853 } 854 return 0; 855} 856 857static inline int LoadBitmap(struct av7110 *av7110, 858 u16 dx, u16 dy, int inc, u8 __user * data) 859{ 860 u16 format; 861 int bpp; 862 int i; 863 int d, delta; 864 u8 c; 865 int ret; 866 867 dprintk(4, "%p\n", av7110); 868 869 format = bpp2bit[av7110->osdbpp[av7110->osdwin]]; 870 871 av7110->bmp_state = BMP_LOADING; 872 if (format == OSD_BITMAP8) { 873 bpp=8; delta = 1; 874 } else if (format == OSD_BITMAP4) { 875 bpp=4; delta = 2; 876 } else if (format == OSD_BITMAP2) { 877 bpp=2; delta = 4; 878 } else if (format == OSD_BITMAP1) { 879 bpp=1; delta = 8; 880 } else { 881 av7110->bmp_state = BMP_NONE; 882 return -EINVAL; 883 } 884 av7110->bmplen = ((dx * dy * bpp + 7) & ~7) / 8; 885 av7110->bmpp = 0; 886 if (av7110->bmplen > 32768) { 887 av7110->bmp_state = BMP_NONE; 888 return -EINVAL; 889 } 890 for (i = 0; i < dy; i++) { 891 if (copy_from_user(av7110->bmpbuf + 1024 + i * dx, data + i * inc, dx)) { 892 av7110->bmp_state = BMP_NONE; 893 return -EINVAL; 894 } 895 } 896 if (format != OSD_BITMAP8) { 897 for (i = 0; i < dx * dy / delta; i++) { 898 c = ((u8 *)av7110->bmpbuf)[1024 + i * delta + delta - 1]; 899 for (d = delta - 2; d >= 0; d--) { 900 c |= (((u8 *)av7110->bmpbuf)[1024 + i * delta + d] 901 << ((delta - d - 1) * bpp)); 902 ((u8 *)av7110->bmpbuf)[1024 + i] = c; 903 } 904 } 905 } 906 av7110->bmplen += 1024; 907 dprintk(4, "av7110_fw_cmd: LoadBmp size %d\n", av7110->bmplen); 908 ret = av7110_fw_cmd(av7110, COMTYPE_OSD, LoadBmp, 3, format, dx, dy); 909 if (!ret) 910 ret = WaitUntilBmpLoaded(av7110); 911 return ret; 912} 913 914static int BlitBitmap(struct av7110 *av7110, u16 x, u16 y) 915{ 916 dprintk(4, "%p\n", av7110); 917 918 return av7110_fw_cmd(av7110, COMTYPE_OSD, BlitBmp, 4, av7110->osdwin, x, y, 0); 919} 920 921static inline int ReleaseBitmap(struct av7110 *av7110) 922{ 923 dprintk(4, "%p\n", av7110); 924 925 if (av7110->bmp_state != BMP_LOADED && FW_VERSION(av7110->arm_app) < 0x261e) 926 return -1; 927 if (av7110->bmp_state == BMP_LOADING) 928 dprintk(1,"ReleaseBitmap called while BMP_LOADING\n"); 929 av7110->bmp_state = BMP_NONE; 930 return av7110_fw_cmd(av7110, COMTYPE_OSD, ReleaseBmp, 0); 931} 932 933static u32 RGB2YUV(u16 R, u16 G, u16 B) 934{ 935 u16 y, u, v; 936 u16 Y, Cr, Cb; 937 938 y = R * 77 + G * 150 + B * 29; /* Luma=0.299R+0.587G+0.114B 0..65535 */ 939 u = 2048 + B * 8 -(y >> 5); /* Cr 0..4095 */ 940 v = 2048 + R * 8 -(y >> 5); /* Cb 0..4095 */ 941 942 Y = y / 256; 943 Cb = u / 16; 944 Cr = v / 16; 945 946 return Cr | (Cb << 16) | (Y << 8); 947} 948 949static int OSDSetColor(struct av7110 *av7110, u8 color, u8 r, u8 g, u8 b, u8 blend) 950{ 951 int ret; 952 953 u16 ch, cl; 954 u32 yuv; 955 956 yuv = blend ? RGB2YUV(r,g,b) : 0; 957 cl = (yuv & 0xffff); 958 ch = ((yuv >> 16) & 0xffff); 959 ret = SetColor_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]], 960 color, ch, cl); 961 if (!ret) 962 ret = SetBlend_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]], 963 color, ((blend >> 4) & 0x0f)); 964 return ret; 965} 966 967static int OSDSetPalette(struct av7110 *av7110, u32 __user * colors, u8 first, u8 last) 968{ 969 int i; 970 int length = last - first + 1; 971 972 if (length * 4 > DATA_BUFF3_SIZE) 973 return -EINVAL; 974 975 for (i = 0; i < length; i++) { 976 u32 color, blend, yuv; 977 978 if (get_user(color, colors + i)) 979 return -EFAULT; 980 blend = (color & 0xF0000000) >> 4; 981 yuv = blend ? RGB2YUV(color & 0xFF, (color >> 8) & 0xFF, 982 (color >> 16) & 0xFF) | blend : 0; 983 yuv = ((yuv & 0xFFFF0000) >> 16) | ((yuv & 0x0000FFFF) << 16); 984 wdebi(av7110, DEBINOSWAP, DATA_BUFF3_BASE + i * 4, yuv, 4); 985 } 986 return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Palette, 4, 987 av7110->osdwin, 988 bpp2pal[av7110->osdbpp[av7110->osdwin]], 989 first, last); 990} 991 992static int OSDSetBlock(struct av7110 *av7110, int x0, int y0, 993 int x1, int y1, int inc, u8 __user * data) 994{ 995 uint w, h, bpp, bpl, size, lpb, bnum, brest; 996 int i; 997 int rc,release_rc; 998 999 w = x1 - x0 + 1; 1000 h = y1 - y0 + 1; 1001 if (inc <= 0) 1002 inc = w; 1003 if (w <= 0 || w > 720 || h <= 0 || h > 576) 1004 return -EINVAL; 1005 bpp = av7110->osdbpp[av7110->osdwin] + 1; 1006 bpl = ((w * bpp + 7) & ~7) / 8; 1007 size = h * bpl; 1008 lpb = (32 * 1024) / bpl; 1009 bnum = size / (lpb * bpl); 1010 brest = size - bnum * lpb * bpl; 1011 1012 if (av7110->bmp_state == BMP_LOADING) { 1013 /* possible if syscall is repeated by -ERESTARTSYS and if firmware cannot abort */ 1014 BUG_ON (FW_VERSION(av7110->arm_app) >= 0x261e); 1015 rc = WaitUntilBmpLoaded(av7110); 1016 if (rc) 1017 return rc; 1018 /* just continue. This should work for all fw versions 1019 * if bnum==1 && !brest && LoadBitmap was successful 1020 */ 1021 } 1022 1023 rc = 0; 1024 for (i = 0; i < bnum; i++) { 1025 rc = LoadBitmap(av7110, w, lpb, inc, data); 1026 if (rc) 1027 break; 1028 rc = BlitBitmap(av7110, x0, y0 + i * lpb); 1029 if (rc) 1030 break; 1031 data += lpb * inc; 1032 } 1033 if (!rc && brest) { 1034 rc = LoadBitmap(av7110, w, brest / bpl, inc, data); 1035 if (!rc) 1036 rc = BlitBitmap(av7110, x0, y0 + bnum * lpb); 1037 } 1038 release_rc = ReleaseBitmap(av7110); 1039 if (!rc) 1040 rc = release_rc; 1041 if (rc) 1042 dprintk(1,"returns %d\n",rc); 1043 return rc; 1044} 1045 1046int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc) 1047{ 1048 int ret; 1049 1050 if (mutex_lock_interruptible(&av7110->osd_mutex)) 1051 return -ERESTARTSYS; 1052 1053 switch (dc->cmd) { 1054 case OSD_Close: 1055 ret = DestroyOSDWindow(av7110, av7110->osdwin); 1056 break; 1057 case OSD_Open: 1058 av7110->osdbpp[av7110->osdwin] = (dc->color - 1) & 7; 1059 ret = CreateOSDWindow(av7110, av7110->osdwin, 1060 bpp2bit[av7110->osdbpp[av7110->osdwin]], 1061 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1); 1062 if (ret) 1063 break; 1064 if (!dc->data) { 1065 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0); 1066 if (ret) 1067 break; 1068 ret = SetColorBlend(av7110, av7110->osdwin); 1069 } 1070 break; 1071 case OSD_Show: 1072 ret = MoveWindowRel(av7110, av7110->osdwin, 0, 0); 1073 break; 1074 case OSD_Hide: 1075 ret = HideWindow(av7110, av7110->osdwin); 1076 break; 1077 case OSD_Clear: 1078 ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, 0); 1079 break; 1080 case OSD_Fill: 1081 ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, dc->color); 1082 break; 1083 case OSD_SetColor: 1084 ret = OSDSetColor(av7110, dc->color, dc->x0, dc->y0, dc->x1, dc->y1); 1085 break; 1086 case OSD_SetPalette: 1087 if (FW_VERSION(av7110->arm_app) >= 0x2618) 1088 ret = OSDSetPalette(av7110, dc->data, dc->color, dc->x0); 1089 else { 1090 int i, len = dc->x0-dc->color+1; 1091 u8 __user *colors = (u8 __user *)dc->data; 1092 u8 r, g = 0, b = 0, blend = 0; 1093 ret = 0; 1094 for (i = 0; i<len; i++) { 1095 if (get_user(r, colors + i * 4) || 1096 get_user(g, colors + i * 4 + 1) || 1097 get_user(b, colors + i * 4 + 2) || 1098 get_user(blend, colors + i * 4 + 3)) { 1099 ret = -EFAULT; 1100 break; 1101 } 1102 ret = OSDSetColor(av7110, dc->color + i, r, g, b, blend); 1103 if (ret) 1104 break; 1105 } 1106 } 1107 break; 1108 case OSD_SetPixel: 1109 ret = DrawLine(av7110, av7110->osdwin, 1110 dc->x0, dc->y0, 0, 0, dc->color); 1111 break; 1112 case OSD_SetRow: 1113 dc->y1 = dc->y0; 1114 /* fall through */ 1115 case OSD_SetBlock: 1116 ret = OSDSetBlock(av7110, dc->x0, dc->y0, dc->x1, dc->y1, dc->color, dc->data); 1117 break; 1118 case OSD_FillRow: 1119 ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0, 1120 dc->x1-dc->x0+1, dc->y1, dc->color); 1121 break; 1122 case OSD_FillBlock: 1123 ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0, 1124 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1, dc->color); 1125 break; 1126 case OSD_Line: 1127 ret = DrawLine(av7110, av7110->osdwin, 1128 dc->x0, dc->y0, dc->x1 - dc->x0, dc->y1 - dc->y0, dc->color); 1129 break; 1130 case OSD_Text: 1131 { 1132 char textbuf[240]; 1133 1134 if (strncpy_from_user(textbuf, dc->data, 240) < 0) { 1135 ret = -EFAULT; 1136 break; 1137 } 1138 textbuf[239] = 0; 1139 if (dc->x1 > 3) 1140 dc->x1 = 3; 1141 ret = SetFont(av7110, av7110->osdwin, dc->x1, 1142 (u16) (dc->color & 0xffff), (u16) (dc->color >> 16)); 1143 if (!ret) 1144 ret = FlushText(av7110); 1145 if (!ret) 1146 ret = WriteText(av7110, av7110->osdwin, dc->x0, dc->y0, textbuf); 1147 break; 1148 } 1149 case OSD_SetWindow: 1150 if (dc->x0 < 1 || dc->x0 > 7) 1151 ret = -EINVAL; 1152 else { 1153 av7110->osdwin = dc->x0; 1154 ret = 0; 1155 } 1156 break; 1157 case OSD_MoveWindow: 1158 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0); 1159 if (!ret) 1160 ret = SetColorBlend(av7110, av7110->osdwin); 1161 break; 1162 case OSD_OpenRaw: 1163 if (dc->color < OSD_BITMAP1 || dc->color > OSD_CURSOR) { 1164 ret = -EINVAL; 1165 break; 1166 } 1167 if (dc->color >= OSD_BITMAP1 && dc->color <= OSD_BITMAP8HR) 1168 av7110->osdbpp[av7110->osdwin] = (1 << (dc->color & 3)) - 1; 1169 else 1170 av7110->osdbpp[av7110->osdwin] = 0; 1171 ret = CreateOSDWindow(av7110, av7110->osdwin, (osd_raw_window_t)dc->color, 1172 dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1); 1173 if (ret) 1174 break; 1175 if (!dc->data) { 1176 ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0); 1177 if (!ret) 1178 ret = SetColorBlend(av7110, av7110->osdwin); 1179 } 1180 break; 1181 default: 1182 ret = -EINVAL; 1183 break; 1184 } 1185 1186 mutex_unlock(&av7110->osd_mutex); 1187 if (ret==-ERESTARTSYS) 1188 dprintk(1, "av7110_osd_cmd(%d) returns with -ERESTARTSYS\n",dc->cmd); 1189 else if (ret) 1190 dprintk(1, "av7110_osd_cmd(%d) returns with %d\n",dc->cmd,ret); 1191 1192 return ret; 1193} 1194 1195int av7110_osd_capability(struct av7110 *av7110, osd_cap_t *cap) 1196{ 1197 switch (cap->cmd) { 1198 case OSD_CAP_MEMSIZE: 1199 if (FW_4M_SDRAM(av7110->arm_app)) 1200 cap->val = 1000000; 1201 else 1202 cap->val = 92000; 1203 return 0; 1204 default: 1205 return -EINVAL; 1206 } 1207} 1208#endif /* CONFIG_DVB_AV7110_OSD */ 1209