Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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, &regval);
^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");