linux/drivers/staging/go7007/s2250-board.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2008 Sensoray Company Inc.
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License (Version 2) as
   6 * published by the Free Software Foundation.
   7 *
   8 * This program is distributed in the hope that it will be useful,
   9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11 * GNU General Public License for more details.
  12 *
  13 * You should have received a copy of the GNU General Public License
  14 * along with this program; if not, write to the Free Software Foundation,
  15 * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  16 */
  17
  18#include <linux/module.h>
  19#include <linux/init.h>
  20#include <linux/usb.h>
  21#include <linux/i2c.h>
  22#include <linux/videodev2.h>
  23#include <media/v4l2-common.h>
  24#include "s2250-loader.h"
  25#include "go7007-priv.h"
  26#include "wis-i2c.h"
  27
  28#define TLV320_ADDRESS      0x34
  29#define VPX322_ADDR_ANALOGCONTROL1      0x02
  30#define VPX322_ADDR_BRIGHTNESS0         0x0127
  31#define VPX322_ADDR_BRIGHTNESS1         0x0131
  32#define VPX322_ADDR_CONTRAST0           0x0128
  33#define VPX322_ADDR_CONTRAST1           0x0132
  34#define VPX322_ADDR_HUE                 0x00dc
  35#define VPX322_ADDR_SAT                 0x0030
  36
  37struct go7007_usb_board {
  38        unsigned int flags;
  39        struct go7007_board_info main_info;
  40};
  41
  42struct go7007_usb {
  43        struct go7007_usb_board *board;
  44        struct mutex i2c_lock;
  45        struct usb_device *usbdev;
  46        struct urb *video_urbs[8];
  47        struct urb *audio_urbs[8];
  48        struct urb *intr_urb;
  49};
  50
  51static unsigned char aud_regs[] = {
  52        0x1e, 0x00,
  53        0x00, 0x17,
  54        0x02, 0x17,
  55        0x04, 0xf9,
  56        0x06, 0xf9,
  57        0x08, 0x02,
  58        0x0a, 0x00,
  59        0x0c, 0x00,
  60        0x0a, 0x00,
  61        0x0c, 0x00,
  62        0x0e, 0x02,
  63        0x10, 0x00,
  64        0x12, 0x01,
  65        0x00, 0x00,
  66};
  67
  68
  69static unsigned char vid_regs[] = {
  70        0xF2, 0x0f,
  71        0xAA, 0x00,
  72        0xF8, 0xff,
  73        0x00, 0x00,
  74};
  75
  76static u16 vid_regs_fp[] = {
  77        0x028, 0x067,
  78        0x120, 0x016,
  79        0x121, 0xcF2,
  80        0x122, 0x0F2,
  81        0x123, 0x00c,
  82        0x124, 0x2d0,
  83        0x125, 0x2e0,
  84        0x126, 0x004,
  85        0x128, 0x1E0,
  86        0x12A, 0x016,
  87        0x12B, 0x0F2,
  88        0x12C, 0x0F2,
  89        0x12D, 0x00c,
  90        0x12E, 0x2d0,
  91        0x12F, 0x2e0,
  92        0x130, 0x004,
  93        0x132, 0x1E0,
  94        0x140, 0x060,
  95        0x153, 0x00C,
  96        0x154, 0x200,
  97        0x150, 0x801,
  98        0x000, 0x000
  99};
 100
 101/* PAL specific values */
 102static u16 vid_regs_fp_pal[] =
 103{
 104        0x120, 0x017,
 105        0x121, 0xd22,
 106        0x122, 0x122,
 107        0x12A, 0x017,
 108        0x12B, 0x122,
 109        0x12C, 0x122,
 110        0x140, 0x060,
 111        0x000, 0x000,
 112};
 113
 114struct s2250 {
 115        v4l2_std_id std;
 116        int input;
 117        int brightness;
 118        int contrast;
 119        int saturation;
 120        int hue;
 121        int reg12b_val;
 122        int audio_input;
 123        struct i2c_client *audio;
 124};
 125
 126/* from go7007-usb.c which is Copyright (C) 2005-2006 Micronas USA Inc.*/
 127static int go7007_usb_vendor_request(struct go7007 *go, u16 request,
 128        u16 value, u16 index, void *transfer_buffer, int length, int in)
 129{
 130        struct go7007_usb *usb = go->hpi_context;
 131        int timeout = 5000;
 132
 133        if (in) {
 134                return usb_control_msg(usb->usbdev,
 135                                usb_rcvctrlpipe(usb->usbdev, 0), request,
 136                                USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
 137                                value, index, transfer_buffer, length, timeout);
 138        } else {
 139                return usb_control_msg(usb->usbdev,
 140                                usb_sndctrlpipe(usb->usbdev, 0), request,
 141                                USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 142                                value, index, transfer_buffer, length, timeout);
 143        }
 144}
 145/* end from go7007-usb.c which is Copyright (C) 2005-2006 Micronas USA Inc.*/
 146
 147static int write_reg(struct i2c_client *client, u8 reg, u8 value)
 148{
 149        struct go7007 *go = i2c_get_adapdata(client->adapter);
 150        struct go7007_usb *usb;
 151        int rc;
 152        int dev_addr = client->addr;
 153        u8 *buf;
 154
 155        if (go == NULL)
 156                return -ENODEV;
 157
 158        if (go->status == STATUS_SHUTDOWN)
 159                return -EBUSY;
 160
 161        buf = kzalloc(16, GFP_KERNEL);
 162        if (buf == NULL)
 163                return -ENOMEM;
 164
 165        usb = go->hpi_context;
 166        if (mutex_lock_interruptible(&usb->i2c_lock) != 0) {
 167                printk(KERN_INFO "i2c lock failed\n");
 168                kfree(buf);
 169                return -EINTR;
 170        }
 171        rc = go7007_usb_vendor_request(go, 0x55, dev_addr,
 172                                       (reg<<8 | value),
 173                                       buf,
 174                                       16, 1);
 175
 176        mutex_unlock(&usb->i2c_lock);
 177        kfree(buf);
 178        return rc;
 179}
 180
 181static int write_reg_fp(struct i2c_client *client, u16 addr, u16 val)
 182{
 183        struct go7007 *go = i2c_get_adapdata(client->adapter);
 184        struct go7007_usb *usb;
 185        u8 *buf;
 186        struct s2250 *dec = i2c_get_clientdata(client);
 187
 188        if (go == NULL)
 189                return -ENODEV;
 190
 191        if (go->status == STATUS_SHUTDOWN)
 192                return -EBUSY;
 193
 194        buf = kzalloc(16, GFP_KERNEL);
 195
 196        if (buf == NULL)
 197                return -ENOMEM;
 198
 199
 200
 201        memset(buf, 0xcd, 6);
 202
 203        usb = go->hpi_context;
 204        if (mutex_lock_interruptible(&usb->i2c_lock) != 0) {
 205                printk(KERN_INFO "i2c lock failed\n");
 206                kfree(buf);
 207                return -EINTR;
 208        }
 209        if (go7007_usb_vendor_request(go, 0x57, addr, val, buf, 16, 1) < 0) {
 210                kfree(buf);
 211                return -EFAULT;
 212        }
 213
 214        mutex_unlock(&usb->i2c_lock);
 215        if (buf[0] == 0) {
 216                unsigned int subaddr, val_read;
 217
 218                subaddr = (buf[4] << 8) + buf[5];
 219                val_read = (buf[2] << 8) + buf[3];
 220                kfree(buf);
 221                if (val_read != val) {
 222                        printk(KERN_INFO "invalid fp write %x %x\n",
 223                               val_read, val);
 224                        return -EFAULT;
 225                }
 226                if (subaddr != addr) {
 227                        printk(KERN_INFO "invalid fp write addr %x %x\n",
 228                               subaddr, addr);
 229                        return -EFAULT;
 230                }
 231        } else {
 232                kfree(buf);
 233                return -EFAULT;
 234        }
 235
 236        /* save last 12b value */
 237        if (addr == 0x12b)
 238                dec->reg12b_val = val;
 239
 240        return 0;
 241}
 242
 243static int read_reg_fp(struct i2c_client *client, u16 addr, u16 *val)
 244{
 245        struct go7007 *go = i2c_get_adapdata(client->adapter);
 246        struct go7007_usb *usb;
 247        u8 *buf;
 248
 249        if (go == NULL)
 250                return -ENODEV;
 251
 252        if (go->status == STATUS_SHUTDOWN)
 253                return -EBUSY;
 254
 255        buf = kzalloc(16, GFP_KERNEL);
 256
 257        if (buf == NULL)
 258                return -ENOMEM;
 259
 260
 261
 262        memset(buf, 0xcd, 6);
 263        usb = go->hpi_context;
 264        if (mutex_lock_interruptible(&usb->i2c_lock) != 0) {
 265                printk(KERN_INFO "i2c lock failed\n");
 266                kfree(buf);
 267                return -EINTR;
 268        }
 269        if (go7007_usb_vendor_request(go, 0x58, addr, 0, buf, 16, 1) < 0) {
 270                kfree(buf);
 271                return -EFAULT;
 272        }
 273        mutex_unlock(&usb->i2c_lock);
 274
 275        *val = (buf[0] << 8) | buf[1];
 276        kfree(buf);
 277
 278        return 0;
 279}
 280
 281
 282static int write_regs(struct i2c_client *client, u8 *regs)
 283{
 284        int i;
 285
 286        for (i = 0; !((regs[i] == 0x00) && (regs[i+1] == 0x00)); i += 2) {
 287                if (write_reg(client, regs[i], regs[i+1]) < 0) {
 288                        printk(KERN_INFO "s2250: failed\n");
 289                        return -1;
 290                }
 291        }
 292        return 0;
 293}
 294
 295static int write_regs_fp(struct i2c_client *client, u16 *regs)
 296{
 297        int i;
 298
 299        for (i = 0; !((regs[i] == 0x00) && (regs[i+1] == 0x00)); i += 2) {
 300                if (write_reg_fp(client, regs[i], regs[i+1]) < 0) {
 301                        printk(KERN_INFO "s2250: failed fp\n");
 302                        return -1;
 303                }
 304        }
 305        return 0;
 306}
 307
 308
 309static int s2250_command(struct i2c_client *client,
 310                         unsigned int cmd, void *arg)
 311{
 312        struct s2250 *dec = i2c_get_clientdata(client);
 313
 314        switch (cmd) {
 315        case VIDIOC_S_INPUT:
 316        {
 317                int vidsys;
 318                int *input = arg;
 319
 320                vidsys = (dec->std == V4L2_STD_NTSC) ? 0x01 : 0x00;
 321                if (*input == 0) {
 322                        /* composite */
 323                        write_reg_fp(client, 0x20, 0x020 | vidsys);
 324                        write_reg_fp(client, 0x21, 0x662);
 325                        write_reg_fp(client, 0x140, 0x060);
 326                } else {
 327                        /* S-Video */
 328                        write_reg_fp(client, 0x20, 0x040 | vidsys);
 329                        write_reg_fp(client, 0x21, 0x666);
 330                        write_reg_fp(client, 0x140, 0x060);
 331                }
 332                dec->input = *input;
 333                break;
 334        }
 335        case VIDIOC_S_STD:
 336        {
 337                v4l2_std_id *std = arg;
 338                u16 vidsource;
 339
 340                vidsource = (dec->input == 1) ? 0x040 : 0x020;
 341                dec->std = *std;
 342                switch (dec->std) {
 343                case V4L2_STD_NTSC:
 344                        write_regs_fp(client, vid_regs_fp);
 345                        write_reg_fp(client, 0x20, vidsource | 1);
 346                        break;
 347                case V4L2_STD_PAL:
 348                        write_regs_fp(client, vid_regs_fp);
 349                        write_regs_fp(client, vid_regs_fp_pal);
 350                        write_reg_fp(client, 0x20, vidsource);
 351                        break;
 352                default:
 353                        return -EINVAL;
 354                }
 355                break;
 356        }
 357        case VIDIOC_QUERYCTRL:
 358        {
 359                struct v4l2_queryctrl *ctrl = arg;
 360                static const u32 user_ctrls[] = {
 361                        V4L2_CID_BRIGHTNESS,
 362                        V4L2_CID_CONTRAST,
 363                        V4L2_CID_SATURATION,
 364                        V4L2_CID_HUE,
 365                        0
 366                };
 367                static const u32 *ctrl_classes[] = {
 368                        user_ctrls,
 369                        NULL
 370                };
 371
 372                ctrl->id = v4l2_ctrl_next(ctrl_classes, ctrl->id);
 373                switch (ctrl->id) {
 374                case V4L2_CID_BRIGHTNESS:
 375                        v4l2_ctrl_query_fill(ctrl, 0, 100, 1, 50);
 376                        break;
 377                case V4L2_CID_CONTRAST:
 378                        v4l2_ctrl_query_fill(ctrl, 0, 100, 1, 50);
 379                        break;
 380                case V4L2_CID_SATURATION:
 381                        v4l2_ctrl_query_fill(ctrl, 0, 100, 1, 50);
 382                        break;
 383                case V4L2_CID_HUE:
 384                        v4l2_ctrl_query_fill(ctrl, -50, 50, 1, 0);
 385                        break;
 386                default:
 387                        ctrl->name[0] = '\0';
 388                        return -EINVAL;
 389                }
 390                break;
 391        }
 392        case VIDIOC_S_CTRL:
 393        {
 394                struct v4l2_control *ctrl = arg;
 395                int value1;
 396                u16 oldvalue;
 397
 398                switch (ctrl->id) {
 399                case V4L2_CID_BRIGHTNESS:
 400                        if (ctrl->value > 100)
 401                                dec->brightness = 100;
 402                        else if (ctrl->value < 0)
 403                                dec->brightness = 0;
 404                        else
 405                                dec->brightness = ctrl->value;
 406                        value1 = (dec->brightness - 50) * 255 / 100;
 407                        read_reg_fp(client, VPX322_ADDR_BRIGHTNESS0, &oldvalue);
 408                        write_reg_fp(client, VPX322_ADDR_BRIGHTNESS0,
 409                                     value1 | (oldvalue & ~0xff));
 410                        read_reg_fp(client, VPX322_ADDR_BRIGHTNESS1, &oldvalue);
 411                        write_reg_fp(client, VPX322_ADDR_BRIGHTNESS1,
 412                                     value1 | (oldvalue & ~0xff));
 413                        write_reg_fp(client, 0x140, 0x60);
 414                        break;
 415                case V4L2_CID_CONTRAST:
 416                        if (ctrl->value > 100)
 417                                dec->contrast = 100;
 418                        else if (ctrl->value < 0)
 419                                dec->contrast = 0;
 420                        else
 421                                dec->contrast = ctrl->value;
 422                        value1 = dec->contrast * 0x40 / 100;
 423                        if (value1 > 0x3f)
 424                                value1 = 0x3f; /* max */
 425                        read_reg_fp(client, VPX322_ADDR_CONTRAST0, &oldvalue);
 426                        write_reg_fp(client, VPX322_ADDR_CONTRAST0,
 427                                     value1 | (oldvalue & ~0x3f));
 428                        read_reg_fp(client, VPX322_ADDR_CONTRAST1, &oldvalue);
 429                        write_reg_fp(client, VPX322_ADDR_CONTRAST1,
 430                                     value1 | (oldvalue & ~0x3f));
 431                        write_reg_fp(client, 0x140, 0x60);
 432                        break;
 433                case V4L2_CID_SATURATION:
 434                        if (ctrl->value > 127)
 435                                dec->saturation = 127;
 436                        else if (ctrl->value < 0)
 437                                dec->saturation = 0;
 438                        else
 439                                dec->saturation = ctrl->value;
 440
 441                        value1 = dec->saturation * 4140 / 100;
 442                        if (value1 > 4094)
 443                                value1 = 4094;
 444                        write_reg_fp(client, VPX322_ADDR_SAT, value1);
 445                        break;
 446                case V4L2_CID_HUE:
 447                        if (ctrl->value > 50)
 448                                dec->hue = 50;
 449                        else if (ctrl->value < -50)
 450                                dec->hue = -50;
 451                        else
 452                                dec->hue = ctrl->value;
 453                        /* clamp the hue range */
 454                        value1 = dec->hue * 280 / 50;
 455                        write_reg_fp(client, VPX322_ADDR_HUE, value1);
 456                        break;
 457                }
 458                break;
 459        }
 460        case VIDIOC_G_CTRL:
 461        {
 462                struct v4l2_control *ctrl = arg;
 463
 464                switch (ctrl->id) {
 465                case V4L2_CID_BRIGHTNESS:
 466                        ctrl->value = dec->brightness;
 467                        break;
 468                case V4L2_CID_CONTRAST:
 469                        ctrl->value = dec->contrast;
 470                        break;
 471                case V4L2_CID_SATURATION:
 472                        ctrl->value = dec->saturation;
 473                        break;
 474                case V4L2_CID_HUE:
 475                        ctrl->value = dec->hue;
 476                        break;
 477                }
 478                break;
 479        }
 480        case VIDIOC_S_FMT:
 481        {
 482                struct v4l2_format *fmt = arg;
 483                if (fmt->fmt.pix.height < 640) {
 484                        write_reg_fp(client, 0x12b, dec->reg12b_val | 0x400);
 485                        write_reg_fp(client, 0x140, 0x060);
 486                } else {
 487                        write_reg_fp(client, 0x12b, dec->reg12b_val & ~0x400);
 488                        write_reg_fp(client, 0x140, 0x060);
 489                }
 490                return 0;
 491        }
 492        case VIDIOC_G_AUDIO:
 493        {
 494                struct v4l2_audio *audio = arg;
 495
 496                memset(audio, 0, sizeof(*audio));
 497                audio->index = dec->audio_input;
 498                /* fall through */
 499        }
 500        case VIDIOC_ENUMAUDIO:
 501        {
 502                struct v4l2_audio *audio = arg;
 503
 504                switch (audio->index) {
 505                case 0:
 506                        strcpy(audio->name, "Line In");
 507                        break;
 508                case 1:
 509                        strcpy(audio->name, "Mic");
 510                        break;
 511                case 2:
 512                        strcpy(audio->name, "Mic Boost");
 513                        break;
 514                default:
 515                        audio->name[0] = '\0';
 516                        return 0;
 517                }
 518                audio->capability = V4L2_AUDCAP_STEREO;
 519                audio->mode = 0;
 520                return 0;
 521        }
 522        case VIDIOC_S_AUDIO:
 523        {
 524                struct v4l2_audio *audio = arg;
 525
 526                switch (audio->index) {
 527                case 0:
 528                        write_reg(dec->audio, 0x08, 0x02); /* Line In */
 529                        break;
 530                case 1:
 531                        write_reg(dec->audio, 0x08, 0x04); /* Mic */
 532                        break;
 533                case 2:
 534                        write_reg(dec->audio, 0x08, 0x05); /* Mic Boost */
 535                        break;
 536                default:
 537                        return -EINVAL;
 538                }
 539                dec->audio_input = audio->index;
 540                return 0;
 541        }
 542
 543        default:
 544                printk(KERN_INFO "s2250: unknown command 0x%x\n", cmd);
 545                break;
 546        }
 547        return 0;
 548}
 549
 550static int s2250_probe(struct i2c_client *client,
 551                       const struct i2c_device_id *id)
 552{
 553        struct i2c_client *audio;
 554        struct i2c_adapter *adapter = client->adapter;
 555        struct s2250 *dec;
 556        u8 *data;
 557        struct go7007 *go = i2c_get_adapdata(adapter);
 558        struct go7007_usb *usb = go->hpi_context;
 559
 560        audio = i2c_new_dummy(adapter, TLV320_ADDRESS >> 1);
 561        if (audio == NULL)
 562                return -ENOMEM;
 563
 564        dec = kmalloc(sizeof(struct s2250), GFP_KERNEL);
 565        if (dec == NULL) {
 566                i2c_unregister_device(audio);
 567                return -ENOMEM;
 568        }
 569
 570        dec->std = V4L2_STD_NTSC;
 571        dec->brightness = 50;
 572        dec->contrast = 50;
 573        dec->saturation = 50;
 574        dec->hue = 0;
 575        dec->audio = audio;
 576        i2c_set_clientdata(client, dec);
 577
 578        printk(KERN_DEBUG
 579               "s2250: initializing video decoder on %s\n",
 580               adapter->name);
 581
 582        /* initialize the audio */
 583        if (write_regs(audio, aud_regs) < 0) {
 584                printk(KERN_ERR
 585                       "s2250: error initializing audio\n");
 586                i2c_unregister_device(audio);
 587                kfree(dec);
 588                return 0;
 589        }
 590
 591        if (write_regs(client, vid_regs) < 0) {
 592                printk(KERN_ERR
 593                       "s2250: error initializing decoder\n");
 594                i2c_unregister_device(audio);
 595                kfree(dec);
 596                return 0;
 597        }
 598        if (write_regs_fp(client, vid_regs_fp) < 0) {
 599                printk(KERN_ERR
 600                       "s2250: error initializing decoder\n");
 601                i2c_unregister_device(audio);
 602                kfree(dec);
 603                return 0;
 604        }
 605        /* set default channel */
 606        /* composite */
 607        write_reg_fp(client, 0x20, 0x020 | 1);
 608        write_reg_fp(client, 0x21, 0x662);
 609        write_reg_fp(client, 0x140, 0x060);
 610
 611        /* set default audio input */
 612        dec->audio_input = 0;
 613        write_reg(client, 0x08, 0x02); /* Line In */
 614
 615        if (mutex_lock_interruptible(&usb->i2c_lock) == 0) {
 616                data = kzalloc(16, GFP_KERNEL);
 617                if (data != NULL) {
 618                        int rc;
 619                        rc = go7007_usb_vendor_request(go, 0x41, 0, 0,
 620                                                       data, 16, 1);
 621                        if (rc > 0) {
 622                                u8 mask;
 623                                data[0] = 0;
 624                                mask = 1<<5;
 625                                data[0] &= ~mask;
 626                                data[1] |= mask;
 627                                go7007_usb_vendor_request(go, 0x40, 0,
 628                                                          (data[1]<<8)
 629                                                          + data[1],
 630                                                          data, 16, 0);
 631                        }
 632                        kfree(data);
 633                }
 634                mutex_unlock(&usb->i2c_lock);
 635        }
 636
 637        printk("s2250: initialized successfully\n");
 638        return 0;
 639}
 640
 641static int s2250_remove(struct i2c_client *client)
 642{
 643        struct s2250 *dec = i2c_get_clientdata(client);
 644
 645        i2c_set_clientdata(client, NULL);
 646        i2c_unregister_device(dec->audio);
 647        kfree(dec);
 648        return 0;
 649}
 650
 651static struct i2c_device_id s2250_id[] = {
 652        { "s2250_board", 0 },
 653        { }
 654};
 655
 656static struct i2c_driver s2250_driver = {
 657        .driver = {
 658                .name   = "Sensoray 2250 board driver",
 659        },
 660        .probe          = s2250_probe,
 661        .remove         = s2250_remove,
 662        .command        = s2250_command,
 663        .id_table       = s2250_id,
 664};
 665
 666static int __init s2250_init(void)
 667{
 668        int r;
 669
 670        r = s2250loader_init();
 671        if (r < 0)
 672                return r;
 673
 674        r = i2c_add_driver(&s2250_driver);
 675        if (r < 0)
 676                s2250loader_cleanup();
 677
 678        return r;
 679}
 680
 681static void __exit s2250_cleanup(void)
 682{
 683        i2c_del_driver(&s2250_driver);
 684
 685        s2250loader_cleanup();
 686}
 687
 688module_init(s2250_init);
 689module_exit(s2250_cleanup);
 690
 691MODULE_AUTHOR("");
 692MODULE_DESCRIPTION("Board driver for Sensoryray 2250");
 693MODULE_LICENSE("GPL v2");
 694