linux/drivers/media/video/cx23885/cx23885-ioctl.c
<<
>>
Prefs
   1/*
   2 *  Driver for the Conexant CX23885/7/8 PCIe bridge
   3 *
   4 *  Various common ioctl() support functions
   5 *
   6 *  Copyright (c) 2009 Andy Walls <awalls@md.metrocast.net>
   7 *
   8 *  This program is free software; you can redistribute it and/or modify
   9 *  it under the terms of the GNU General Public License as published by
  10 *  the Free Software Foundation; either version 2 of the License, or
  11 *  (at your option) any later version.
  12 *
  13 *  This program is distributed in the hope that it will be useful,
  14 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 *
  17 *  GNU General Public License for more details.
  18 *
  19 *  You should have received a copy of the GNU General Public License
  20 *  along with this program; if not, write to the Free Software
  21 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22 */
  23
  24#include "cx23885.h"
  25#include <media/v4l2-chip-ident.h>
  26
  27int cx23885_g_chip_ident(struct file *file, void *fh,
  28                         struct v4l2_dbg_chip_ident *chip)
  29{
  30        struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev;
  31        int err = 0;
  32        u8 rev;
  33
  34        chip->ident = V4L2_IDENT_NONE;
  35        chip->revision = 0;
  36        switch (chip->match.type) {
  37        case V4L2_CHIP_MATCH_HOST:
  38                switch (chip->match.addr) {
  39                case 0:
  40                        rev = cx_read(RDR_CFG2) & 0xff;
  41                        switch (dev->pci->device) {
  42                        case 0x8852:
  43                                /* rev 0x04 could be '885 or '888. Pick '888. */
  44                                if (rev == 0x04)
  45                                        chip->ident = V4L2_IDENT_CX23888;
  46                                else
  47                                        chip->ident = V4L2_IDENT_CX23885;
  48                                break;
  49                        case 0x8880:
  50                                if (rev == 0x0e || rev == 0x0f)
  51                                        chip->ident = V4L2_IDENT_CX23887;
  52                                else
  53                                        chip->ident = V4L2_IDENT_CX23888;
  54                                break;
  55                        default:
  56                                chip->ident = V4L2_IDENT_UNKNOWN;
  57                                break;
  58                        }
  59                        chip->revision = (dev->pci->device << 16) | (rev << 8) |
  60                                         (dev->hwrevision & 0xff);
  61                        break;
  62                case 1:
  63                        if (dev->v4l_device != NULL) {
  64                                chip->ident = V4L2_IDENT_CX23417;
  65                                chip->revision = 0;
  66                        }
  67                        break;
  68                case 2:
  69                        /*
  70                         * The integrated IR controller on the CX23888 is
  71                         * host chip 2.  It may not be used/initialized or sd_ir
  72                         * may be pointing at the cx25840 subdevice for the
  73                         * IR controller on the CX23885.  Thus we find it
  74                         * without using the dev->sd_ir pointer.
  75                         */
  76                        call_hw(dev, CX23885_HW_888_IR, core, g_chip_ident,
  77                                chip);
  78                        break;
  79                default:
  80                        err = -EINVAL; /* per V4L2 spec */
  81                        break;
  82                }
  83                break;
  84        case V4L2_CHIP_MATCH_I2C_DRIVER:
  85                /* If needed, returns V4L2_IDENT_AMBIGUOUS without extra work */
  86                call_all(dev, core, g_chip_ident, chip);
  87                break;
  88        case V4L2_CHIP_MATCH_I2C_ADDR:
  89                /*
  90                 * We could return V4L2_IDENT_UNKNOWN, but we don't do the work
  91                 * to look if a chip is at the address with no driver.  That's a
  92                 * dangerous thing to do with EEPROMs anyway.
  93                 */
  94                call_all(dev, core, g_chip_ident, chip);
  95                break;
  96        default:
  97                err = -EINVAL;
  98                break;
  99        }
 100        return err;
 101}
 102
 103#ifdef CONFIG_VIDEO_ADV_DEBUG
 104static int cx23885_g_host_register(struct cx23885_dev *dev,
 105                                   struct v4l2_dbg_register *reg)
 106{
 107        if ((reg->reg & 0x3) != 0 || reg->reg >= pci_resource_len(dev->pci, 0))
 108                return -EINVAL;
 109
 110        reg->size = 4;
 111        reg->val = cx_read(reg->reg);
 112        return 0;
 113}
 114
 115static int cx23417_g_register(struct cx23885_dev *dev,
 116                              struct v4l2_dbg_register *reg)
 117{
 118        u32 value;
 119
 120        if (dev->v4l_device == NULL)
 121                return -EINVAL;
 122
 123        if ((reg->reg & 0x3) != 0 || reg->reg >= 0x10000)
 124                return -EINVAL;
 125
 126        if (mc417_register_read(dev, (u16) reg->reg, &value))
 127                return -EINVAL; /* V4L2 spec, but -EREMOTEIO really */
 128
 129        reg->size = 4;
 130        reg->val = value;
 131        return 0;
 132}
 133
 134int cx23885_g_register(struct file *file, void *fh,
 135                       struct v4l2_dbg_register *reg)
 136{
 137        struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev;
 138
 139        if (!capable(CAP_SYS_ADMIN))
 140                return -EPERM;
 141
 142        if (reg->match.type == V4L2_CHIP_MATCH_HOST) {
 143                switch (reg->match.addr) {
 144                case 0:
 145                        return cx23885_g_host_register(dev, reg);
 146                case 1:
 147                        return cx23417_g_register(dev, reg);
 148                default:
 149                        break;
 150                }
 151        }
 152
 153        /* FIXME - any error returns should not be ignored */
 154        call_all(dev, core, g_register, reg);
 155        return 0;
 156}
 157
 158static int cx23885_s_host_register(struct cx23885_dev *dev,
 159                                   struct v4l2_dbg_register *reg)
 160{
 161        if ((reg->reg & 0x3) != 0 || reg->reg >= pci_resource_len(dev->pci, 0))
 162                return -EINVAL;
 163
 164        reg->size = 4;
 165        cx_write(reg->reg, reg->val);
 166        return 0;
 167}
 168
 169static int cx23417_s_register(struct cx23885_dev *dev,
 170                              struct v4l2_dbg_register *reg)
 171{
 172        if (dev->v4l_device == NULL)
 173                return -EINVAL;
 174
 175        if ((reg->reg & 0x3) != 0 || reg->reg >= 0x10000)
 176                return -EINVAL;
 177
 178        if (mc417_register_write(dev, (u16) reg->reg, (u32) reg->val))
 179                return -EINVAL; /* V4L2 spec, but -EREMOTEIO really */
 180
 181        reg->size = 4;
 182        return 0;
 183}
 184
 185int cx23885_s_register(struct file *file, void *fh,
 186                       struct v4l2_dbg_register *reg)
 187{
 188        struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev;
 189
 190        if (!capable(CAP_SYS_ADMIN))
 191                return -EPERM;
 192
 193        if (reg->match.type == V4L2_CHIP_MATCH_HOST) {
 194                switch (reg->match.addr) {
 195                case 0:
 196                        return cx23885_s_host_register(dev, reg);
 197                case 1:
 198                        return cx23417_s_register(dev, reg);
 199                default:
 200                        break;
 201                }
 202        }
 203
 204        /* FIXME - any error returns should not be ignored */
 205        call_all(dev, core, s_register, reg);
 206        return 0;
 207}
 208#endif
 209