^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * cxd2099.c: Driver for the Sony CXD2099AR Common Interface Controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2010-2013 Digital Devices GmbH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * This program is free software; you can redistribute it and/or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * modify it under the terms of the GNU General Public License
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * version 2 only, as published by the Free Software Foundation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * This program is distributed in the hope that it will be useful,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * but WITHOUT ANY WARRANTY; without even the implied warranty of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * GNU General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/wait.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "cxd2099.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static int buffermode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) module_param(buffermode, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) MODULE_PARM_DESC(buffermode, "Enable CXD2099AR buffer mode (default: disabled)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static int read_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct cxd {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct dvb_ca_en50221 en;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct cxd2099_cfg cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) u8 regs[0x23];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) u8 lastaddress;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) u8 clk_reg_f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) u8 clk_reg_b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) int mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) int ready;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) int dr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) int write_busy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) int slot_stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) u8 amem[1024];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) int amem_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) int cammode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct mutex lock; /* device access lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) u8 rbuf[1028];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) u8 wbuf[1028];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static int read_block(struct cxd *ci, u8 adr, u8 *data, u16 n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) int status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (ci->lastaddress != adr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) status = regmap_write(ci->regmap, 0, adr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (!status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) ci->lastaddress = adr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) while (n) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) int len = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (ci->cfg.max_i2c && len > ci->cfg.max_i2c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) len = ci->cfg.max_i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) status = regmap_raw_read(ci->regmap, 1, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) data += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) n -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static int read_reg(struct cxd *ci, u8 reg, u8 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return read_block(ci, reg, val, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static int read_pccard(struct cxd *ci, u16 address, u8 *data, u8 n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) u8 addr[2] = {address & 0xff, address >> 8};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) status = regmap_raw_write(ci->regmap, 2, addr, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (!status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) status = regmap_raw_read(ci->regmap, 3, data, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static int write_pccard(struct cxd *ci, u16 address, u8 *data, u8 n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) u8 addr[2] = {address & 0xff, address >> 8};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) status = regmap_raw_write(ci->regmap, 2, addr, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (!status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) u8 buf[256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) memcpy(buf, data, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) status = regmap_raw_write(ci->regmap, 3, buf, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static int read_io(struct cxd *ci, u16 address, unsigned int *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) u8 addr[2] = {address & 0xff, address >> 8};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) status = regmap_raw_write(ci->regmap, 2, addr, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (!status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) status = regmap_read(ci->regmap, 3, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static int write_io(struct cxd *ci, u16 address, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) u8 addr[2] = {address & 0xff, address >> 8};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) status = regmap_raw_write(ci->regmap, 2, addr, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (!status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) status = regmap_write(ci->regmap, 3, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static int write_regm(struct cxd *ci, u8 reg, u8 val, u8 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) int status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) unsigned int regval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (ci->lastaddress != reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) status = regmap_write(ci->regmap, 0, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (!status && reg >= 6 && reg <= 8 && mask != 0xff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) status = regmap_read(ci->regmap, 1, ®val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) ci->regs[reg] = regval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) ci->lastaddress = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) ci->regs[reg] = (ci->regs[reg] & (~mask)) | val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (!status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) status = regmap_write(ci->regmap, 1, ci->regs[reg]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (reg == 0x20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) ci->regs[reg] &= 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) static int write_reg(struct cxd *ci, u8 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return write_regm(ci, reg, val, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static int write_block(struct cxd *ci, u8 adr, u8 *data, u16 n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) int status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) u8 *buf = ci->wbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (ci->lastaddress != adr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) status = regmap_write(ci->regmap, 0, adr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) ci->lastaddress = adr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) while (n) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) int len = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (ci->cfg.max_i2c && (len + 1 > ci->cfg.max_i2c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) len = ci->cfg.max_i2c - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) memcpy(buf, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) status = regmap_raw_write(ci->regmap, 1, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) n -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) data += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) static void set_mode(struct cxd *ci, int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (mode == ci->mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) case 0x00: /* IO mem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) write_regm(ci, 0x06, 0x00, 0x07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) case 0x01: /* ATT mem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) write_regm(ci, 0x06, 0x02, 0x07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) ci->mode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static void cam_mode(struct cxd *ci, int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) u8 dummy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (mode == ci->cammode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) case 0x00:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) write_regm(ci, 0x20, 0x80, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) case 0x01:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (!ci->en.read_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) ci->write_busy = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) dev_info(&ci->client->dev, "enable cam buffer mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) write_reg(ci, 0x0d, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) write_reg(ci, 0x0e, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) write_regm(ci, 0x08, 0x40, 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) read_reg(ci, 0x12, &dummy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) write_regm(ci, 0x08, 0x80, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) ci->cammode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) static int init(struct cxd *ci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) mutex_lock(&ci->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) ci->mode = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) status = write_reg(ci, 0x00, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) status = write_reg(ci, 0x01, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) status = write_reg(ci, 0x02, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) status = write_reg(ci, 0x03, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) status = write_reg(ci, 0x05, 0xFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) status = write_reg(ci, 0x06, 0x1F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) status = write_reg(ci, 0x07, 0x1F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) status = write_reg(ci, 0x08, 0x28);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) status = write_reg(ci, 0x14, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) /* TOSTRT = 8, Mode B (gated clock), falling Edge,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * Serial, POL=HIGH, MSB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) status = write_reg(ci, 0x0A, 0xA7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) status = write_reg(ci, 0x0B, 0x33);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) status = write_reg(ci, 0x0C, 0x33);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) status = write_regm(ci, 0x14, 0x00, 0x0F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) status = write_reg(ci, 0x15, ci->clk_reg_b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) status = write_regm(ci, 0x16, 0x00, 0x0F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) status = write_reg(ci, 0x17, ci->clk_reg_f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (ci->cfg.clock_mode == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) /* bitrate*2^13/ 72000 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) u32 reg = ((ci->cfg.bitrate << 13) + 71999) / 72000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (ci->cfg.polarity) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) status = write_reg(ci, 0x09, 0x6f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) status = write_reg(ci, 0x09, 0x6d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) status = write_reg(ci, 0x20, 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) status = write_reg(ci, 0x21, (reg >> 8) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) status = write_reg(ci, 0x22, reg & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) } else if (ci->cfg.clock_mode == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (ci->cfg.polarity) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) status = write_reg(ci, 0x09, 0x6f); /* D */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) status = write_reg(ci, 0x09, 0x6d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) status = write_reg(ci, 0x20, 0x68);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) status = write_reg(ci, 0x21, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) status = write_reg(ci, 0x22, 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (ci->cfg.polarity) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) status = write_reg(ci, 0x09, 0x4f); /* C */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) status = write_reg(ci, 0x09, 0x4d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) status = write_reg(ci, 0x20, 0x28);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) status = write_reg(ci, 0x21, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) status = write_reg(ci, 0x22, 0x07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) status = write_regm(ci, 0x20, 0x80, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) status = write_regm(ci, 0x03, 0x02, 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) status = write_reg(ci, 0x01, 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) status = write_reg(ci, 0x00, 0x31);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) /* Put TS in bypass */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) status = write_regm(ci, 0x09, 0x08, 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) ci->cammode = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) cam_mode(ci, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) } while (0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) mutex_unlock(&ci->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) static int read_attribute_mem(struct dvb_ca_en50221 *ca,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) int slot, int address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) struct cxd *ci = ca->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) mutex_lock(&ci->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) set_mode(ci, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) read_pccard(ci, address, &val, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) mutex_unlock(&ci->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) static int write_attribute_mem(struct dvb_ca_en50221 *ca, int slot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) int address, u8 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) struct cxd *ci = ca->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) mutex_lock(&ci->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) set_mode(ci, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) write_pccard(ci, address, &value, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) mutex_unlock(&ci->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) static int read_cam_control(struct dvb_ca_en50221 *ca,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) int slot, u8 address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) struct cxd *ci = ca->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) mutex_lock(&ci->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) set_mode(ci, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) read_io(ci, address, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) mutex_unlock(&ci->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) static int write_cam_control(struct dvb_ca_en50221 *ca, int slot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) u8 address, u8 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) struct cxd *ci = ca->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) mutex_lock(&ci->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) set_mode(ci, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) write_io(ci, address, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) mutex_unlock(&ci->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) static int slot_reset(struct dvb_ca_en50221 *ca, int slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) struct cxd *ci = ca->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (ci->cammode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) read_data(ca, slot, ci->rbuf, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) mutex_lock(&ci->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) cam_mode(ci, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) write_reg(ci, 0x00, 0x21);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) write_reg(ci, 0x06, 0x1F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) write_reg(ci, 0x00, 0x31);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) write_regm(ci, 0x20, 0x80, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) write_reg(ci, 0x03, 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) ci->ready = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) ci->mode = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) for (i = 0; i < 100; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) usleep_range(10000, 11000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (ci->ready)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) mutex_unlock(&ci->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) struct cxd *ci = ca->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) dev_dbg(&ci->client->dev, "%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) if (ci->cammode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) read_data(ca, slot, ci->rbuf, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) mutex_lock(&ci->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) write_reg(ci, 0x00, 0x21);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) write_reg(ci, 0x06, 0x1F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) msleep(300);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) write_regm(ci, 0x09, 0x08, 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) write_regm(ci, 0x20, 0x80, 0x80); /* Reset CAM Mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) write_regm(ci, 0x06, 0x07, 0x07); /* Clear IO Mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) ci->mode = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) ci->write_busy = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) mutex_unlock(&ci->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) static int slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) struct cxd *ci = ca->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) mutex_lock(&ci->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) write_regm(ci, 0x09, 0x00, 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) set_mode(ci, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) cam_mode(ci, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) mutex_unlock(&ci->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) static int campoll(struct cxd *ci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) u8 istat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) read_reg(ci, 0x04, &istat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (!istat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) write_reg(ci, 0x05, istat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (istat & 0x40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) ci->dr = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) if (istat & 0x20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) ci->write_busy = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (istat & 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) u8 slotstat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) read_reg(ci, 0x01, &slotstat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (!(2 & slotstat)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (!ci->slot_stat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) ci->slot_stat |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) DVB_CA_EN50221_POLL_CAM_PRESENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) write_regm(ci, 0x03, 0x08, 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (ci->slot_stat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) ci->slot_stat = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) write_regm(ci, 0x03, 0x00, 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) dev_info(&ci->client->dev, "NO CAM\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) ci->ready = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if ((istat & 8) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) ci->slot_stat == DVB_CA_EN50221_POLL_CAM_PRESENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) ci->ready = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) ci->slot_stat |= DVB_CA_EN50221_POLL_CAM_READY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) static int poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) struct cxd *ci = ca->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) u8 slotstat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) mutex_lock(&ci->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) campoll(ci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) read_reg(ci, 0x01, &slotstat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) mutex_unlock(&ci->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) return ci->slot_stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) static int read_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) struct cxd *ci = ca->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) u8 msb, lsb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) u16 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) mutex_lock(&ci->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) campoll(ci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) mutex_unlock(&ci->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (!ci->dr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) mutex_lock(&ci->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) read_reg(ci, 0x0f, &msb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) read_reg(ci, 0x10, &lsb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) len = ((u16)msb << 8) | lsb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) if (len > ecount || len < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) /* read it anyway or cxd may hang */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) read_block(ci, 0x12, ci->rbuf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) mutex_unlock(&ci->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) read_block(ci, 0x12, ebuf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) ci->dr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) mutex_unlock(&ci->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) static int write_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) struct cxd *ci = ca->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) if (ci->write_busy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) mutex_lock(&ci->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) write_reg(ci, 0x0d, ecount >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) write_reg(ci, 0x0e, ecount & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) write_block(ci, 0x11, ebuf, ecount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) ci->write_busy = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) mutex_unlock(&ci->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return ecount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) static const struct dvb_ca_en50221 en_templ = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) .read_attribute_mem = read_attribute_mem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) .write_attribute_mem = write_attribute_mem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) .read_cam_control = read_cam_control,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) .write_cam_control = write_cam_control,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) .slot_reset = slot_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) .slot_shutdown = slot_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) .slot_ts_enable = slot_ts_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) .poll_slot_status = poll_slot_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) .read_data = read_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) .write_data = write_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) static int cxd2099_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) struct cxd *ci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) struct cxd2099_cfg *cfg = client->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) static const struct regmap_config rm_cfg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) .reg_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) .val_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) ci = kzalloc(sizeof(*ci), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if (!ci) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) ci->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) memcpy(&ci->cfg, cfg, sizeof(ci->cfg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) ci->regmap = regmap_init_i2c(client, &rm_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) if (IS_ERR(ci->regmap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) ret = PTR_ERR(ci->regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) goto err_kfree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) ret = regmap_read(ci->regmap, 0x00, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) dev_info(&client->dev, "No CXD2099AR detected at 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) client->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) goto err_rmexit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) mutex_init(&ci->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) ci->lastaddress = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) ci->clk_reg_b = 0x4a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) ci->clk_reg_f = 0x1b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) ci->en = en_templ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) ci->en.data = ci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) init(ci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) dev_info(&client->dev, "Attached CXD2099AR at 0x%02x\n", client->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) *cfg->en = &ci->en;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) if (!buffermode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) ci->en.read_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) ci->en.write_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) dev_info(&client->dev, "Using CXD2099AR buffer mode");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) i2c_set_clientdata(client, ci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) err_rmexit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) regmap_exit(ci->regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) err_kfree:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) kfree(ci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) static int cxd2099_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) struct cxd *ci = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) regmap_exit(ci->regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) kfree(ci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) static const struct i2c_device_id cxd2099_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) {"cxd2099", 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) MODULE_DEVICE_TABLE(i2c, cxd2099_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) static struct i2c_driver cxd2099_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) .name = "cxd2099",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) .probe = cxd2099_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) .remove = cxd2099_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) .id_table = cxd2099_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) module_i2c_driver(cxd2099_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) MODULE_DESCRIPTION("Sony CXD2099AR Common Interface controller driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) MODULE_AUTHOR("Ralph Metzler");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) MODULE_LICENSE("GPL v2");