290 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*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 818 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 case59 * 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");290