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