cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

zd1301.c (7091B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * ZyDAS ZD1301 driver (USB interface)
      4 *
      5 * Copyright (C) 2015 Antti Palosaari <crope@iki.fi>
      6 */
      7
      8#include "dvb_usb.h"
      9#include "zd1301_demod.h"
     10#include "mt2060.h"
     11#include <linux/i2c.h>
     12#include <linux/platform_device.h>
     13
     14DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
     15
     16struct zd1301_dev {
     17	#define BUF_LEN 8
     18	u8 buf[BUF_LEN]; /* bulk USB control message */
     19	struct zd1301_demod_platform_data demod_pdata;
     20	struct mt2060_platform_data mt2060_pdata;
     21	struct platform_device *platform_device_demod;
     22	struct i2c_client *i2c_client_tuner;
     23};
     24
     25static int zd1301_ctrl_msg(struct dvb_usb_device *d, const u8 *wbuf,
     26			   unsigned int wlen, u8 *rbuf, unsigned int rlen)
     27{
     28	struct zd1301_dev *dev = d_to_priv(d);
     29	struct usb_interface *intf = d->intf;
     30	int ret, actual_length;
     31
     32	mutex_lock(&d->usb_mutex);
     33
     34	memcpy(&dev->buf, wbuf, wlen);
     35
     36	dev_dbg(&intf->dev, ">>> %*ph\n", wlen, dev->buf);
     37
     38	ret = usb_bulk_msg(d->udev, usb_sndbulkpipe(d->udev, 0x04), dev->buf,
     39			   wlen, &actual_length, 1000);
     40	if (ret) {
     41		dev_err(&intf->dev, "1st usb_bulk_msg() failed %d\n", ret);
     42		goto err_mutex_unlock;
     43	}
     44
     45	if (rlen) {
     46		ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, 0x83),
     47				   dev->buf, rlen, &actual_length, 1000);
     48		if (ret) {
     49			dev_err(&intf->dev,
     50				"2nd usb_bulk_msg() failed %d\n", ret);
     51			goto err_mutex_unlock;
     52		}
     53
     54		dev_dbg(&intf->dev, "<<< %*ph\n", actual_length, dev->buf);
     55
     56		if (actual_length != rlen) {
     57			/*
     58			 * Chip replies often with 3 byte len stub. On that case
     59			 * we have to query new reply.
     60			 */
     61			dev_dbg(&intf->dev, "repeating reply message\n");
     62
     63			ret = usb_bulk_msg(d->udev,
     64					   usb_rcvbulkpipe(d->udev, 0x83),
     65					   dev->buf, rlen, &actual_length,
     66					   1000);
     67			if (ret) {
     68				dev_err(&intf->dev,
     69					"3rd usb_bulk_msg() failed %d\n", ret);
     70				goto err_mutex_unlock;
     71			}
     72
     73			dev_dbg(&intf->dev,
     74				"<<< %*ph\n", actual_length, dev->buf);
     75		}
     76
     77		memcpy(rbuf, dev->buf, rlen);
     78	}
     79
     80err_mutex_unlock:
     81	mutex_unlock(&d->usb_mutex);
     82	return ret;
     83}
     84
     85static int zd1301_demod_wreg(void *reg_priv, u16 reg, u8 val)
     86{
     87	struct dvb_usb_device *d = reg_priv;
     88	struct usb_interface *intf = d->intf;
     89	int ret;
     90	u8 buf[7] = {0x07, 0x00, 0x03, 0x01,
     91		     (reg >> 0) & 0xff, (reg >> 8) & 0xff, val};
     92
     93	ret = zd1301_ctrl_msg(d, buf, 7, NULL, 0);
     94	if (ret)
     95		goto err;
     96
     97	return 0;
     98err:
     99	dev_dbg(&intf->dev, "failed=%d\n", ret);
    100	return ret;
    101}
    102
    103static int zd1301_demod_rreg(void *reg_priv, u16 reg, u8 *val)
    104{
    105	struct dvb_usb_device *d = reg_priv;
    106	struct usb_interface *intf = d->intf;
    107	int ret;
    108	u8 buf[7] = {0x07, 0x00, 0x04, 0x01,
    109		     (reg >> 0) & 0xff, (reg >> 8) & 0xff, 0};
    110
    111	ret = zd1301_ctrl_msg(d, buf, 7, buf, 7);
    112	if (ret)
    113		goto err;
    114
    115	*val = buf[6];
    116
    117	return 0;
    118err:
    119	dev_dbg(&intf->dev, "failed=%d\n", ret);
    120	return ret;
    121}
    122
    123static int zd1301_frontend_attach(struct dvb_usb_adapter *adap)
    124{
    125	struct dvb_usb_device *d = adap_to_d(adap);
    126	struct zd1301_dev *dev = adap_to_priv(adap);
    127	struct usb_interface *intf = d->intf;
    128	struct platform_device *pdev;
    129	struct i2c_client *client;
    130	struct i2c_board_info board_info;
    131	struct i2c_adapter *adapter;
    132	struct dvb_frontend *frontend;
    133	int ret;
    134
    135	dev_dbg(&intf->dev, "\n");
    136
    137	/* Add platform demod */
    138	dev->demod_pdata.reg_priv = d;
    139	dev->demod_pdata.reg_read = zd1301_demod_rreg;
    140	dev->demod_pdata.reg_write = zd1301_demod_wreg;
    141	request_module("%s", "zd1301_demod");
    142	pdev = platform_device_register_data(&intf->dev,
    143					     "zd1301_demod",
    144					     PLATFORM_DEVID_AUTO,
    145					     &dev->demod_pdata,
    146					     sizeof(dev->demod_pdata));
    147	if (IS_ERR(pdev)) {
    148		ret = PTR_ERR(pdev);
    149		goto err;
    150	}
    151	if (!pdev->dev.driver) {
    152		ret = -ENODEV;
    153		goto err_platform_device_unregister;
    154	}
    155	if (!try_module_get(pdev->dev.driver->owner)) {
    156		ret = -ENODEV;
    157		goto err_platform_device_unregister;
    158	}
    159
    160	adapter = zd1301_demod_get_i2c_adapter(pdev);
    161	frontend = zd1301_demod_get_dvb_frontend(pdev);
    162	if (!adapter || !frontend) {
    163		ret = -ENODEV;
    164		goto err_module_put_demod;
    165	}
    166
    167	/* Add I2C tuner */
    168	dev->mt2060_pdata.i2c_write_max = 9;
    169	dev->mt2060_pdata.dvb_frontend = frontend;
    170	memset(&board_info, 0, sizeof(board_info));
    171	strscpy(board_info.type, "mt2060", I2C_NAME_SIZE);
    172	board_info.addr = 0x60;
    173	board_info.platform_data = &dev->mt2060_pdata;
    174	request_module("%s", "mt2060");
    175	client = i2c_new_client_device(adapter, &board_info);
    176	if (!i2c_client_has_driver(client)) {
    177		ret = -ENODEV;
    178		goto err_module_put_demod;
    179	}
    180	if (!try_module_get(client->dev.driver->owner)) {
    181		ret = -ENODEV;
    182		goto err_i2c_unregister_device;
    183	}
    184
    185	dev->platform_device_demod = pdev;
    186	dev->i2c_client_tuner = client;
    187	adap->fe[0] = frontend;
    188
    189	return 0;
    190err_i2c_unregister_device:
    191	i2c_unregister_device(client);
    192err_module_put_demod:
    193	module_put(pdev->dev.driver->owner);
    194err_platform_device_unregister:
    195	platform_device_unregister(pdev);
    196err:
    197	dev_dbg(&intf->dev, "failed=%d\n", ret);
    198	return ret;
    199}
    200
    201static int zd1301_frontend_detach(struct dvb_usb_adapter *adap)
    202{
    203	struct dvb_usb_device *d = adap_to_d(adap);
    204	struct zd1301_dev *dev = d_to_priv(d);
    205	struct usb_interface *intf = d->intf;
    206	struct platform_device *pdev;
    207	struct i2c_client *client;
    208
    209	dev_dbg(&intf->dev, "\n");
    210
    211	client = dev->i2c_client_tuner;
    212	pdev = dev->platform_device_demod;
    213
    214	/* Remove I2C tuner */
    215	if (client) {
    216		module_put(client->dev.driver->owner);
    217		i2c_unregister_device(client);
    218	}
    219
    220	/* Remove platform demod */
    221	if (pdev) {
    222		module_put(pdev->dev.driver->owner);
    223		platform_device_unregister(pdev);
    224	}
    225
    226	return 0;
    227}
    228
    229static int zd1301_streaming_ctrl(struct dvb_frontend *fe, int onoff)
    230{
    231	struct dvb_usb_device *d = fe_to_d(fe);
    232	struct usb_interface *intf = d->intf;
    233	int ret;
    234	u8 buf[3] = {0x03, 0x00, onoff ? 0x07 : 0x08};
    235
    236	dev_dbg(&intf->dev, "onoff=%d\n", onoff);
    237
    238	ret = zd1301_ctrl_msg(d, buf, 3, NULL, 0);
    239	if (ret)
    240		goto err;
    241
    242	return 0;
    243err:
    244	dev_dbg(&intf->dev, "failed=%d\n", ret);
    245	return ret;
    246}
    247
    248static const struct dvb_usb_device_properties zd1301_props = {
    249	.driver_name = KBUILD_MODNAME,
    250	.owner = THIS_MODULE,
    251	.adapter_nr = adapter_nr,
    252	.size_of_priv = sizeof(struct zd1301_dev),
    253
    254	.frontend_attach = zd1301_frontend_attach,
    255	.frontend_detach = zd1301_frontend_detach,
    256	.streaming_ctrl  = zd1301_streaming_ctrl,
    257
    258	.num_adapters = 1,
    259	.adapter = {
    260		{
    261			.stream = DVB_USB_STREAM_BULK(0x81, 6, 21 * 188),
    262		},
    263	},
    264};
    265
    266static const struct usb_device_id zd1301_id_table[] = {
    267	{DVB_USB_DEVICE(USB_VID_ZYDAS, 0x13a1, &zd1301_props,
    268			"ZyDAS ZD1301 reference design", NULL)},
    269	{}
    270};
    271MODULE_DEVICE_TABLE(usb, zd1301_id_table);
    272
    273/* Usb specific object needed to register this driver with the usb subsystem */
    274static struct usb_driver zd1301_usb_driver = {
    275	.name = KBUILD_MODNAME,
    276	.id_table = zd1301_id_table,
    277	.probe = dvb_usbv2_probe,
    278	.disconnect = dvb_usbv2_disconnect,
    279	.suspend = dvb_usbv2_suspend,
    280	.resume = dvb_usbv2_resume,
    281	.reset_resume = dvb_usbv2_reset_resume,
    282	.no_dynamic_id = 1,
    283	.soft_unbind = 1,
    284};
    285module_usb_driver(zd1301_usb_driver);
    286
    287MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
    288MODULE_DESCRIPTION("ZyDAS ZD1301 driver");
    289MODULE_LICENSE("GPL");