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-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Driver for AzureWave 6007 DVB-C/T USB2.0 and clones
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (c) Henry Wang <Henry.wang@AzureWave.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * This driver was made publicly available by Terratec, at:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *	http://linux.terratec.de/files/TERRATEC_H7/20110323_TERRATEC_H7_Linux.tar.gz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * The original driver's license is GPL, as declared with MODULE_LICENSE()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  * Copyright (c) 2010-2012 Mauro Carvalho Chehab
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  *	Driver modified by in order to work with upstream drxk driver, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  *	tons of bugs got fixed, and converted to use dvb-usb-v2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include "drxk.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include "mt2063.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <media/dvb_ca_en50221.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include "dvb_usb.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include "cypress_firmware.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #define AZ6007_FIRMWARE "dvb-usb-terratec-h7-az6007.fw"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) static int az6007_xfer_debug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) module_param_named(xfer_debug, az6007_xfer_debug, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) MODULE_PARM_DESC(xfer_debug, "Enable xfer debug");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) /* Known requests (Cypress FX2 firmware + az6007 "private" ones*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #define FX2_OED			0xb5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #define AZ6007_READ_DATA	0xb7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #define AZ6007_I2C_RD		0xb9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #define AZ6007_POWER		0xbc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) #define AZ6007_I2C_WR		0xbd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #define FX2_SCON1		0xc0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #define AZ6007_TS_THROUGH	0xc7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) #define AZ6007_READ_IR		0xb4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) struct az6007_device_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	struct mutex		mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	struct mutex		ca_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	struct dvb_ca_en50221	ca;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	unsigned		warm:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	int			(*gate_ctrl) (struct dvb_frontend *, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	unsigned char		data[4096];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) static struct drxk_config terratec_h7_drxk = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	.adr = 0x29,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	.parallel_ts = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	.dynamic_clk = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	.single_master = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	.enable_merr_cfg = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	.no_i2c_bridge = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	.chunk_size = 64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	.mpeg_out_clk_strength = 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	.qam_demod_parameter_count = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	.microcode_name = "dvb-usb-terratec-h7-drxk.fw",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) static struct drxk_config cablestar_hdci_drxk = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	.adr = 0x29,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	.parallel_ts = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	.dynamic_clk = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	.single_master = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	.enable_merr_cfg = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	.no_i2c_bridge = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	.chunk_size = 64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	.mpeg_out_clk_strength = 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	.qam_demod_parameter_count = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	.microcode_name = "dvb-usb-technisat-cablestar-hdci-drxk.fw",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	struct az6007_device_state *st = fe_to_priv(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	struct dvb_usb_adapter *adap = fe->sec_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	int status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	pr_debug("%s: %s\n", __func__, enable ? "enable" : "disable");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	if (!adap || !st)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	if (enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 		status = st->gate_ctrl(fe, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 		status = st->gate_ctrl(fe, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) static struct mt2063_config az6007_mt2063_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	.tuner_address = 0x60,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	.refclock = 36125000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static int __az6007_read(struct usb_device *udev, u8 req, u16 value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 			    u16 index, u8 *b, int blen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	ret = usb_control_msg(udev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 			      usb_rcvctrlpipe(udev, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 			      req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 			      USB_TYPE_VENDOR | USB_DIR_IN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 			      value, index, b, blen, 5000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 		pr_warn("usb read operation failed. (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	if (az6007_xfer_debug) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		printk(KERN_DEBUG "az6007: IN  req: %02x, value: %04x, index: %04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 		       req, value, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		print_hex_dump_bytes("az6007: payload: ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 				     DUMP_PREFIX_NONE, b, blen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static int az6007_read(struct dvb_usb_device *d, u8 req, u16 value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 			    u16 index, u8 *b, int blen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	struct az6007_device_state *st = d->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	if (mutex_lock_interruptible(&st->mutex) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 		return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	ret = __az6007_read(d->udev, req, value, index, b, blen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	mutex_unlock(&st->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static int __az6007_write(struct usb_device *udev, u8 req, u16 value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 			     u16 index, u8 *b, int blen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	if (az6007_xfer_debug) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		printk(KERN_DEBUG "az6007: OUT req: %02x, value: %04x, index: %04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		       req, value, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		print_hex_dump_bytes("az6007: payload: ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 				     DUMP_PREFIX_NONE, b, blen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	if (blen > 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		pr_err("az6007: tried to write %d bytes, but I2C max size is 64 bytes\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		       blen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		return -EOPNOTSUPP;
^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) 	ret = usb_control_msg(udev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 			      usb_sndctrlpipe(udev, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 			      req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 			      USB_TYPE_VENDOR | USB_DIR_OUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 			      value, index, b, blen, 5000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	if (ret != blen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		pr_err("usb write operation failed. (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static int az6007_write(struct dvb_usb_device *d, u8 req, u16 value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 			    u16 index, u8 *b, int blen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	struct az6007_device_state *st = d->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	if (mutex_lock_interruptible(&st->mutex) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 		return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	ret = __az6007_write(d->udev, req, value, index, b, blen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	mutex_unlock(&st->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) static int az6007_streaming_ctrl(struct dvb_frontend *fe, int onoff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	struct dvb_usb_device *d = fe_to_d(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	pr_debug("%s: %s\n", __func__, onoff ? "enable" : "disable");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	return az6007_write(d, 0xbc, onoff, 0, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) #if IS_ENABLED(CONFIG_RC_CORE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) /* remote control stuff (does not work with my box) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static int az6007_rc_query(struct dvb_usb_device *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	struct az6007_device_state *st = d_to_priv(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	unsigned code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	enum rc_proto proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	if (st->data[1] == 0x44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	if ((st->data[3] ^ st->data[4]) == 0xff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 		if ((st->data[1] ^ st->data[2]) == 0xff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 			code = RC_SCANCODE_NEC(st->data[1], st->data[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 			proto = RC_PROTO_NEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 			code = RC_SCANCODE_NECX(st->data[1] << 8 | st->data[2],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 						st->data[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 			proto = RC_PROTO_NECX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 		code = RC_SCANCODE_NEC32(st->data[1] << 24 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 					 st->data[2] << 16 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 					 st->data[3] << 8  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 					 st->data[4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 		proto = RC_PROTO_NEC32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	rc_keydown(d->rc_dev, proto, code, st->data[5]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) static int az6007_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	pr_debug("Getting az6007 Remote Control properties\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	rc->allowed_protos = RC_PROTO_BIT_NEC | RC_PROTO_BIT_NECX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 						RC_PROTO_BIT_NEC32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	rc->query          = az6007_rc_query;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	rc->interval       = 400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	#define az6007_get_rc_config NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static int az6007_ci_read_attribute_mem(struct dvb_ca_en50221 *ca,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 					int slot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 					int address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	struct az6007_device_state *state = d_to_priv(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	u8 req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	u16 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	u16 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	int blen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	u8 *b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	if (slot != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	b = kmalloc(12, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	if (!b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	mutex_lock(&state->ca_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	req = 0xC1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	value = address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	blen = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	ret = az6007_read(d, req, value, index, b, blen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 		pr_warn("usb in operation failed. (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 		ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 		ret = b[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	mutex_unlock(&state->ca_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	kfree(b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) static int az6007_ci_write_attribute_mem(struct dvb_ca_en50221 *ca,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 					 int slot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 					 int address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 					 u8 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	struct az6007_device_state *state = d_to_priv(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	u8 req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	u16 value1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	u16 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	int blen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	pr_debug("%s(), slot %d\n", __func__, slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	if (slot != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	mutex_lock(&state->ca_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	req = 0xC2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	value1 = address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	index = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	blen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	ret = az6007_write(d, req, value1, index, NULL, blen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 		pr_warn("usb out operation failed. (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	mutex_unlock(&state->ca_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) static int az6007_ci_read_cam_control(struct dvb_ca_en50221 *ca,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 				      int slot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 				      u8 address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	struct az6007_device_state *state = d_to_priv(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	u8 req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	u16 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	u16 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	int blen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	u8 *b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	if (slot != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	b = kmalloc(12, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	if (!b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	mutex_lock(&state->ca_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	req = 0xC3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	value = address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	blen = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	ret = az6007_read(d, req, value, index, b, blen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 		pr_warn("usb in operation failed. (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 		ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 		if (b[0] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 			pr_warn("Read CI IO error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 		ret = b[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 		pr_debug("read cam data = %x from 0x%x\n", b[1], value);
^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) 	mutex_unlock(&state->ca_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	kfree(b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) static int az6007_ci_write_cam_control(struct dvb_ca_en50221 *ca,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 				       int slot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 				       u8 address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 				       u8 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	struct az6007_device_state *state = d_to_priv(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 	u8 req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	u16 value1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	u16 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	int blen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	if (slot != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	mutex_lock(&state->ca_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	req = 0xC4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	value1 = address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	index = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	blen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	ret = az6007_write(d, req, value1, index, NULL, blen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 		pr_warn("usb out operation failed. (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 		goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	mutex_unlock(&state->ca_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	u8 req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	u16 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	u16 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 	int blen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	u8 *b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	b = kmalloc(12, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 	if (!b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	req = 0xC8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 	blen = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	ret = az6007_read(d, req, value, index, b, blen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 		pr_warn("usb in operation failed. (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 		ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	} else{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 		ret = b[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 	kfree(b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) static int az6007_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 	struct az6007_device_state *state = d_to_priv(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 	u8 req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 	u16 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 	u16 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 	int blen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	mutex_lock(&state->ca_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	req = 0xC6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 	value = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 	index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	blen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 	ret = az6007_write(d, req, value, index, NULL, blen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 		pr_warn("usb out operation failed. (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 		goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 	msleep(500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	req = 0xC6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 	value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 	index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 	blen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 	ret = az6007_write(d, req, value, index, NULL, blen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 		pr_warn("usb out operation failed. (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 		goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 	for (i = 0; i < 15; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 		msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 		if (CI_CamReady(ca, slot)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 			pr_debug("CAM Ready\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 	msleep(5000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	mutex_unlock(&state->ca_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) static int az6007_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) {
^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 az6007_ci_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 dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 	struct az6007_device_state *state = d_to_priv(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	u8 req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	u16 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	u16 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 	int blen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 	pr_debug("%s()\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 	mutex_lock(&state->ca_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	req = 0xC7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 	value = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 	index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 	blen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 	ret = az6007_write(d, req, value, index, NULL, blen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 	if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 		pr_warn("usb out operation failed. (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 		goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 	mutex_unlock(&state->ca_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) static int az6007_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 	struct az6007_device_state *state = d_to_priv(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	u8 req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 	u16 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 	u16 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 	int blen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 	u8 *b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 	b = kmalloc(12, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 	if (!b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 	mutex_lock(&state->ca_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 	req = 0xC5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 	value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 	index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 	blen = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 	ret = az6007_read(d, req, value, index, b, blen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 		pr_warn("usb in operation failed. (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 		ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 		ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 	if (!ret && b[0] == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 		ret = DVB_CA_EN50221_POLL_CAM_PRESENT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 		      DVB_CA_EN50221_POLL_CAM_READY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 	mutex_unlock(&state->ca_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 	kfree(b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 	return ret;
^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) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) static void az6007_ci_uninit(struct dvb_usb_device *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 	struct az6007_device_state *state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 	pr_debug("%s()\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 	if (NULL == d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 	state = d_to_priv(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 	if (NULL == state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 	if (NULL == state->ca.data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 	dvb_ca_en50221_release(&state->ca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 	memset(&state->ca, 0, sizeof(state->ca));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) static int az6007_ci_init(struct dvb_usb_adapter *adap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 	struct dvb_usb_device *d = adap_to_d(adap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 	struct az6007_device_state *state = adap_to_priv(adap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 	pr_debug("%s()\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 	mutex_init(&state->ca_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 	state->ca.owner			= THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 	state->ca.read_attribute_mem	= az6007_ci_read_attribute_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 	state->ca.write_attribute_mem	= az6007_ci_write_attribute_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 	state->ca.read_cam_control	= az6007_ci_read_cam_control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 	state->ca.write_cam_control	= az6007_ci_write_cam_control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 	state->ca.slot_reset		= az6007_ci_slot_reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 	state->ca.slot_shutdown		= az6007_ci_slot_shutdown;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 	state->ca.slot_ts_enable	= az6007_ci_slot_ts_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 	state->ca.poll_slot_status	= az6007_ci_poll_slot_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 	state->ca.data			= d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 	ret = dvb_ca_en50221_init(&adap->dvb_adap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 				  &state->ca,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 				  0, /* flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 				  1);/* n_slots */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 	if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 		pr_err("Cannot initialize CI: Error %d.\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 		memset(&state->ca, 0, sizeof(state->ca));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 	pr_debug("CI initialized.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) static int az6007_read_mac_addr(struct dvb_usb_adapter *adap, u8 mac[6])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 	struct dvb_usb_device *d = adap_to_d(adap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 	struct az6007_device_state *st = adap_to_priv(adap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 	ret = az6007_read(d, AZ6007_READ_DATA, 6, 0, st->data, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 	memcpy(mac, st->data, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 	if (ret > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 		pr_debug("%s: mac is %pM\n", __func__, mac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) static int az6007_frontend_attach(struct dvb_usb_adapter *adap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 	struct az6007_device_state *st = adap_to_priv(adap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 	struct dvb_usb_device *d = adap_to_d(adap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 	pr_debug("attaching demod drxk\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 	adap->fe[0] = dvb_attach(drxk_attach, &terratec_h7_drxk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 				 &d->i2c_adap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 	if (!adap->fe[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 	adap->fe[0]->sec_priv = adap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 	st->gate_ctrl = adap->fe[0]->ops.i2c_gate_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 	adap->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 	az6007_ci_init(adap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) static int az6007_cablestar_hdci_frontend_attach(struct dvb_usb_adapter *adap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 	struct az6007_device_state *st = adap_to_priv(adap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 	struct dvb_usb_device *d = adap_to_d(adap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 	pr_debug("attaching demod drxk\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 	adap->fe[0] = dvb_attach(drxk_attach, &cablestar_hdci_drxk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 				 &d->i2c_adap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 	if (!adap->fe[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 	adap->fe[0]->sec_priv = adap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 	st->gate_ctrl = adap->fe[0]->ops.i2c_gate_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 	adap->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 	az6007_ci_init(adap);
^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) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) static int az6007_tuner_attach(struct dvb_usb_adapter *adap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 	struct dvb_usb_device *d = adap_to_d(adap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 	pr_debug("attaching tuner mt2063\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 	/* Attach mt2063 to DVB-C frontend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 	if (adap->fe[0]->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 		adap->fe[0]->ops.i2c_gate_ctrl(adap->fe[0], 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 	if (!dvb_attach(mt2063_attach, adap->fe[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 			&az6007_mt2063_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 			&d->i2c_adap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 	if (adap->fe[0]->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 		adap->fe[0]->ops.i2c_gate_ctrl(adap->fe[0], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) static int az6007_power_ctrl(struct dvb_usb_device *d, int onoff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 	struct az6007_device_state *state = d_to_priv(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 	pr_debug("%s()\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 	if (!state->warm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 		mutex_init(&state->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 		ret = az6007_write(d, AZ6007_POWER, 0, 2, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 		msleep(60);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 		ret = az6007_write(d, AZ6007_POWER, 1, 4, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) 		msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 		ret = az6007_write(d, AZ6007_POWER, 1, 3, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 		msleep(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) 		ret = az6007_write(d, AZ6007_POWER, 1, 4, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) 		msleep(400);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) 		ret = az6007_write(d, FX2_SCON1, 0, 3, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) 		msleep(150);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) 		ret = az6007_write(d, FX2_SCON1, 1, 3, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) 		msleep(430);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) 		ret = az6007_write(d, AZ6007_POWER, 0, 0, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) 		state->warm = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) 	if (!onoff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) 	az6007_write(d, AZ6007_POWER, 0, 0, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) 	az6007_write(d, AZ6007_TS_THROUGH, 0, 0, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) /* I2C */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) 			   int num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) 	struct dvb_usb_device *d = i2c_get_adapdata(adap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 	struct az6007_device_state *st = d_to_priv(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) 	int i, j, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) 	u16 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) 	u16 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) 	int length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) 	u8 req, addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) 	if (mutex_lock_interruptible(&st->mutex) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) 		return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) 	for (i = 0; i < num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) 		addr = msgs[i].addr << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) 		if (((i + 1) < num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) 		    && (msgs[i].len == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) 		    && ((msgs[i].flags & I2C_M_RD) != I2C_M_RD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) 		    && (msgs[i + 1].flags & I2C_M_RD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) 		    && (msgs[i].addr == msgs[i + 1].addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) 			 * A write + read xfer for the same address, where
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) 			 * the first xfer has just 1 byte length.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) 			 * Need to join both into one operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) 			if (az6007_xfer_debug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) 				printk(KERN_DEBUG "az6007: I2C W/R addr=0x%x len=%d/%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) 				       addr, msgs[i].len, msgs[i + 1].len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) 			req = AZ6007_I2C_RD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) 			index = msgs[i].buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) 			value = addr | (1 << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) 			length = 6 + msgs[i + 1].len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) 			len = msgs[i + 1].len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) 			ret = __az6007_read(d->udev, req, value, index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) 					    st->data, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) 			if (ret >= len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) 				for (j = 0; j < len; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) 					msgs[i + 1].buf[j] = st->data[j + 5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) 			} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) 				ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) 			i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) 		} else if (!(msgs[i].flags & I2C_M_RD)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) 			/* write bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) 			if (az6007_xfer_debug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) 				printk(KERN_DEBUG "az6007: I2C W addr=0x%x len=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) 				       addr, msgs[i].len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) 			req = AZ6007_I2C_WR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) 			index = msgs[i].buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) 			value = addr | (1 << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) 			length = msgs[i].len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) 			len = msgs[i].len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) 			for (j = 0; j < len; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) 				st->data[j] = msgs[i].buf[j + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) 			ret =  __az6007_write(d->udev, req, value, index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) 					      st->data, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) 			/* read bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) 			if (az6007_xfer_debug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) 				printk(KERN_DEBUG "az6007: I2C R addr=0x%x len=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) 				       addr, msgs[i].len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) 			req = AZ6007_I2C_RD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) 			index = msgs[i].buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) 			value = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) 			length = msgs[i].len + 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) 			len = msgs[i].len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) 			ret = __az6007_read(d->udev, req, value, index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) 					    st->data, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) 			for (j = 0; j < len; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) 				msgs[i].buf[j] = st->data[j + 5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) 			goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) 	mutex_unlock(&st->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) 		pr_info("%s ERROR: %i\n", __func__, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) 	return num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) static u32 az6007_i2c_func(struct i2c_adapter *adapter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) 	return I2C_FUNC_I2C;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) static struct i2c_algorithm az6007_i2c_algo = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) 	.master_xfer = az6007_i2c_xfer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) 	.functionality = az6007_i2c_func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) static int az6007_identify_state(struct dvb_usb_device *d, const char **name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) 	u8 *mac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) 	pr_debug("Identifying az6007 state\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) 	mac = kmalloc(6, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) 	if (!mac)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) 	/* Try to read the mac address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) 	ret = __az6007_read(d->udev, AZ6007_READ_DATA, 6, 0, mac, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) 	if (ret == 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) 		ret = WARM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) 		ret = COLD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) 	kfree(mac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) 	if (ret == COLD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) 		__az6007_write(d->udev, 0x09, 1, 0, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) 		__az6007_write(d->udev, 0x00, 0, 0, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) 		__az6007_write(d->udev, 0x00, 0, 0, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) 	pr_debug("Device is on %s state\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) 		 ret == WARM ? "warm" : "cold");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) static void az6007_usb_disconnect(struct usb_interface *intf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) 	struct dvb_usb_device *d = usb_get_intfdata(intf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) 	az6007_ci_uninit(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) 	dvb_usbv2_disconnect(intf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) static int az6007_download_firmware(struct dvb_usb_device *d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) 	const struct firmware *fw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) 	pr_debug("Loading az6007 firmware\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) 	return cypress_load_firmware(d->udev, fw, CYPRESS_FX2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) /* DVB USB Driver stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) static struct dvb_usb_device_properties az6007_props = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) 	.driver_name         = KBUILD_MODNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) 	.owner               = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) 	.firmware            = AZ6007_FIRMWARE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) 	.adapter_nr          = adapter_nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) 	.size_of_priv        = sizeof(struct az6007_device_state),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) 	.i2c_algo            = &az6007_i2c_algo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) 	.tuner_attach        = az6007_tuner_attach,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) 	.frontend_attach     = az6007_frontend_attach,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) 	.streaming_ctrl      = az6007_streaming_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) 	.get_rc_config       = az6007_get_rc_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) 	.read_mac_address    = az6007_read_mac_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) 	.download_firmware   = az6007_download_firmware,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) 	.identify_state	     = az6007_identify_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) 	.power_ctrl          = az6007_power_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) 	.num_adapters        = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) 	.adapter             = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) 		{ .stream = DVB_USB_STREAM_BULK(0x02, 10, 4096), }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) static struct dvb_usb_device_properties az6007_cablestar_hdci_props = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) 	.driver_name         = KBUILD_MODNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) 	.owner               = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) 	.firmware            = AZ6007_FIRMWARE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) 	.adapter_nr          = adapter_nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) 	.size_of_priv        = sizeof(struct az6007_device_state),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) 	.i2c_algo            = &az6007_i2c_algo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) 	.tuner_attach        = az6007_tuner_attach,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) 	.frontend_attach     = az6007_cablestar_hdci_frontend_attach,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) 	.streaming_ctrl      = az6007_streaming_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) /* ditch get_rc_config as it can't work (TS35 remote, I believe it's rc5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) 	.get_rc_config       = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) 	.read_mac_address    = az6007_read_mac_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) 	.download_firmware   = az6007_download_firmware,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) 	.identify_state	     = az6007_identify_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) 	.power_ctrl          = az6007_power_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) 	.num_adapters        = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) 	.adapter             = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) 		{ .stream = DVB_USB_STREAM_BULK(0x02, 10, 4096), }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) static const struct usb_device_id az6007_usb_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) 	{DVB_USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_6007,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) 		&az6007_props, "Azurewave 6007", RC_MAP_EMPTY)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) 	{DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) 		&az6007_props, "Terratec H7", RC_MAP_NEC_TERRATEC_CINERGY_XS)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) 	{DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7_2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) 		&az6007_props, "Terratec H7", RC_MAP_NEC_TERRATEC_CINERGY_XS)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) 	{DVB_USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_CABLESTAR_HDCI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) 		&az6007_cablestar_hdci_props, "Technisat CableStar Combo HD CI", RC_MAP_EMPTY)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) 	{0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) MODULE_DEVICE_TABLE(usb, az6007_usb_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) static int az6007_suspend(struct usb_interface *intf, pm_message_t msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) 	struct dvb_usb_device *d = usb_get_intfdata(intf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) 	az6007_ci_uninit(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) 	return dvb_usbv2_suspend(intf, msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) static int az6007_resume(struct usb_interface *intf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) 	struct dvb_usb_device *d = usb_get_intfdata(intf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) 	struct dvb_usb_adapter *adap = &d->adapter[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) 	az6007_ci_init(adap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) 	return dvb_usbv2_resume(intf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) /* usb specific object needed to register this driver with the usb subsystem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) static struct usb_driver az6007_usb_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) 	.name		= KBUILD_MODNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) 	.id_table	= az6007_usb_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) 	.probe		= dvb_usbv2_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) 	.disconnect	= az6007_usb_disconnect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) 	.no_dynamic_id	= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) 	.soft_unbind	= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) 	 * FIXME: need to implement reset_resume, likely with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) 	 * dvb-usb-v2 core support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) 	.suspend	= az6007_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) 	.resume		= az6007_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) module_usb_driver(az6007_usb_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) MODULE_AUTHOR("Henry Wang <Henry.wang@AzureWave.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) MODULE_AUTHOR("Mauro Carvalho Chehab");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) MODULE_DESCRIPTION("Driver for AzureWave 6007 DVB-C/T USB2.0 and clones");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) MODULE_VERSION("2.0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) MODULE_FIRMWARE(AZ6007_FIRMWARE);