isdbt.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759
  1. /*
  2. * drivers/media/isdbt/isdbt.c
  3. *
  4. * isdbt driver
  5. *
  6. * Copyright (C) (2014, Samsung Electronics)
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. */
  19. #include <linux/device.h>
  20. #include <linux/string.h>
  21. #include <linux/clk.h>
  22. #include <linux/mm.h>
  23. #include <linux/slab.h>
  24. #include <linux/input.h>
  25. #include <linux/pm_qos.h>
  26. #include <linux/of_gpio.h>
  27. #include "isdbt.h"
  28. #if defined(CONFIG_MTV_QUALCOMM)
  29. #include <mach/gpiomux.h>
  30. #include <soc/qcom/pm.h>
  31. #elif defined(CONFIG_MTV_EXYNOS)
  32. #include <plat/gpio-cfg.h>
  33. #elif defined(CONFIG_MTV_SPREADTRUM)
  34. #include <mach/pinmap.h>
  35. #endif
  36. #if defined(ISDBT_USE_PMIC)
  37. #include <linux/regulator/machine.h>
  38. #endif
  39. #define ISDBT_WAKE_LOCK_ENABLE
  40. #ifdef ISDBT_WAKE_LOCK_ENABLE
  41. #if defined(CONFIG_MTV_QUALCOMM)
  42. static struct pm_qos_request isdbt_pm_qos_req;
  43. #endif
  44. static struct wake_lock isdbt_wlock;
  45. #endif
  46. static struct isdbt_drv_func *isdbtdrv_func = NULL;
  47. static struct class *isdbt_class = NULL;
  48. static struct isdbt_dt_platform_data *dt_pdata;
  49. static bool isdbt_pwr_on = false;
  50. #if defined(CONFIG_SEC_GPIO_SETTINGS)
  51. static struct device *isdbt_device = NULL;
  52. #else
  53. #if defined(CONFIG_MTV_QUALCOMM)
  54. static struct gpiomux_setting spi_active_config = {
  55. .func = GPIOMUX_FUNC_1,
  56. .drv = GPIOMUX_DRV_2MA,
  57. .pull = GPIOMUX_PULL_DOWN,
  58. };
  59. static struct gpiomux_setting spi_suspend_config = {
  60. .func = GPIOMUX_FUNC_GPIO,
  61. .drv = GPIOMUX_DRV_2MA,
  62. .pull = GPIOMUX_PULL_DOWN,
  63. .dir = GPIOMUX_IN,
  64. };
  65. #elif defined(CONFIG_MTV_SPREADTRUM)
  66. #define SPI_PIN_FUNC_MASK (0x3<<4)
  67. #define SPI_PIN_FUNC_DEF (0x0<<4)
  68. #define SPI_PIN_FUNC_GPIO (0x3<<4)
  69. struct spi_pin_desc {
  70. const char *name;
  71. unsigned int pin_func;
  72. unsigned int reg;
  73. unsigned int gpio;
  74. };
  75. static struct spi_pin_desc spi_pin_group[] = {
  76. {"SPI_MISO", SPI_PIN_FUNC_DEF, REG_PIN_SPI0_DI + CTL_PIN_BASE, 69},
  77. {"SPI_CLK", SPI_PIN_FUNC_DEF, REG_PIN_SPI0_CLK + CTL_PIN_BASE, 70},
  78. {"SPI_MOSI", SPI_PIN_FUNC_DEF, REG_PIN_SPI0_DO + CTL_PIN_BASE, 68},
  79. {"SPI_CS0", SPI_PIN_FUNC_GPIO, REG_PIN_SPI0_CSN + CTL_PIN_BASE, 67}
  80. };
  81. #endif
  82. #endif
  83. #if defined(ISDBT_USE_PMIC)
  84. static void isdbt_control_pmic_pwr(bool on)
  85. {
  86. static struct regulator *reg_isdbt = NULL;
  87. static int prev_on = 0;
  88. int rc = 0;
  89. if(on == prev_on)
  90. return;
  91. if(!reg_isdbt) {
  92. reg_isdbt = regulator_get(NULL, ISDBT_PMIC_NAME);
  93. if (IS_ERR(reg_isdbt)) {
  94. DPRINTK("%s : could not get %s\n", __func__, ISDBT_PMIC_NAME);
  95. reg_isdbt = NULL;
  96. return;
  97. // return -ENODEV;
  98. }
  99. rc = regulator_set_voltage(reg_isdbt, ISDBT_PMIC_VOLTAGE, ISDBT_PMIC_VOLTAGE);
  100. if(rc) {
  101. DPRINTK("%s : set voltage failed for %s, rc = %d\n", __func__, ISDBT_PMIC_NAME, rc);
  102. return;
  103. // return -EINVAL;
  104. }
  105. DPRINTK("%s (get/set) : success\n", __func__);
  106. }
  107. if(on) {
  108. rc = regulator_enable(reg_isdbt);
  109. if(rc) {
  110. DPRINTK("%s : regulator enable failed, rc = %d\n", __func__, rc);
  111. return;
  112. // return rc;
  113. }
  114. DPRINTK("%s (on) : sunccess\n", __func__);
  115. } else {
  116. rc = regulator_disable(reg_isdbt);
  117. if(rc) {
  118. DPRINTK("%s : regulator disable failed, rc = %d\n", __func__, rc);
  119. // return rc;
  120. }
  121. else DPRINTK("%s (on) : success\n", __func__);
  122. }
  123. prev_on = on;
  124. return;
  125. }
  126. #endif
  127. static void isdbt_gpio_set_output(void)
  128. {
  129. gpio_direction_output(dt_pdata->isdbt_pwr_en, 0);
  130. if (gpio_is_valid(dt_pdata->isdbt_pwr_en2))
  131. gpio_direction_output(dt_pdata->isdbt_pwr_en2, 0);
  132. if (gpio_is_valid(dt_pdata->isdbt_rst))
  133. gpio_direction_output(dt_pdata->isdbt_rst, 0);
  134. gpio_direction_input(dt_pdata->isdbt_irq);
  135. }
  136. static void isdbt_gpio_set_input(void)
  137. {
  138. gpio_direction_input(dt_pdata->isdbt_pwr_en);
  139. if (gpio_is_valid(dt_pdata->isdbt_pwr_en2))
  140. gpio_direction_input(dt_pdata->isdbt_pwr_en2);
  141. if (gpio_is_valid(dt_pdata->isdbt_rst))
  142. gpio_direction_input(dt_pdata->isdbt_rst);
  143. }
  144. static void isdbt_gpio_config(bool poweron)
  145. {
  146. #if defined(CONFIG_SEC_GPIO_SETTINGS)
  147. struct pinctrl *isdbt_pinctrl;
  148. /* Get pinctrl if target uses pinctrl */
  149. isdbt_pinctrl = (poweron ? devm_pinctrl_get_select(isdbt_device, "isdbt_gpio_active") : devm_pinctrl_get_select(isdbt_device, "isdbt_gpio_suspend"));
  150. if (IS_ERR(isdbt_pinctrl)) {
  151. DPRINTK("Target does not use pinctrl\n");
  152. isdbt_pinctrl = NULL;
  153. }
  154. #else
  155. #if defined(CONFIG_MTV_QUALCOMM)
  156. if(poweron) {
  157. if(msm_gpiomux_write(dt_pdata->isdbt_spi_mosi, GPIOMUX_ACTIVE, &spi_active_config, NULL) < 0)
  158. DPRINTK("spi_mosi Port request error!!!\n");
  159. if(msm_gpiomux_write(dt_pdata->isdbt_spi_miso, GPIOMUX_ACTIVE, &spi_active_config, NULL) < 0)
  160. DPRINTK("spi_miso Port request error!!!\n");
  161. if(msm_gpiomux_write(dt_pdata->isdbt_spi_cs, GPIOMUX_ACTIVE, &spi_active_config, NULL) < 0)
  162. DPRINTK("spi_cs Port request error!!!\n");
  163. if(msm_gpiomux_write(dt_pdata->isdbt_spi_clk, GPIOMUX_ACTIVE, &spi_active_config, NULL) < 0)
  164. DPRINTK("spi_clk Port request error!!!\n");
  165. } else {
  166. if(msm_gpiomux_write(dt_pdata->isdbt_spi_mosi, GPIOMUX_SUSPENDED, &spi_suspend_config, NULL) < 0)
  167. DPRINTK("spi_mosi Port request error!!!\n");
  168. if(msm_gpiomux_write(dt_pdata->isdbt_spi_miso, GPIOMUX_SUSPENDED, &spi_suspend_config, NULL) < 0)
  169. DPRINTK("spi_miso Port request error!!!\n");
  170. if(msm_gpiomux_write(dt_pdata->isdbt_spi_cs, GPIOMUX_SUSPENDED, &spi_suspend_config, NULL) < 0)
  171. DPRINTK("spi_cs Port request error!!!\n");
  172. if(msm_gpiomux_write(dt_pdata->isdbt_spi_clk, GPIOMUX_SUSPENDED, &spi_suspend_config, NULL) < 0)
  173. DPRINTK("spi_clk Port request error!!!\n");
  174. }
  175. #elif defined(CONFIG_MTV_BROADCOM)
  176. if(poweron) {
  177. struct pin_config SdioPinCfgs;
  178. SdioPinCfgs.name = dt_pdata->isdbt_irq;
  179. pinmux_get_pin_config(&SdioPinCfgs);
  180. SdioPinCfgs.reg.b.slew_rate_ctrl = 0;
  181. pinmux_set_pin_config(&SdioPinCfgs);
  182. SdioPinCfgs.name = dt_pdata->isdbt_rst;
  183. pinmux_get_pin_config(&SdioPinCfgs);
  184. SdioPinCfgs.reg.b.input_dis = 1;
  185. SdioPinCfgs.reg.b.drv_sth = 0;
  186. SdioPinCfgs.func = PF_GPIO00;
  187. SdioPinCfgs.reg.b.sel = 4;
  188. pinmux_set_pin_config(&SdioPinCfgs);
  189. }
  190. #elif defined(CONFIG_MTV_SPREADTRUM)
  191. if(poweron) {
  192. unsigned int reg, gpio, pin_func, value;
  193. unsigned long flags;
  194. int i, regs_count;
  195. regs_count = sizeof(spi_pin_group)/sizeof(struct spi_pin_desc);
  196. for (i = 0; i < regs_count; i++) {
  197. pin_func = spi_pin_group[i].pin_func;
  198. gpio = spi_pin_group[i].gpio;
  199. if (pin_func == SPI_PIN_FUNC_DEF) {
  200. reg = spi_pin_group[i].reg;
  201. /* free the gpios that have request */
  202. // gpio_free(gpio);
  203. local_irq_save(flags);
  204. /* config pin default spi function */
  205. value = ((__raw_readl(reg) & ~SPI_PIN_FUNC_MASK) | SPI_PIN_FUNC_DEF);
  206. __raw_writel(value, reg);
  207. local_irq_restore(flags);
  208. }
  209. else {
  210. /* CS should config output */
  211. gpio_direction_output(gpio, 1);
  212. }
  213. }
  214. }
  215. #endif
  216. #endif
  217. if(poweron)
  218. isdbt_gpio_set_output();
  219. else
  220. isdbt_gpio_set_input();
  221. }
  222. static void isdbt_gpio_on(void)
  223. {
  224. DPRINTK("isdbt_gpio_on\n");
  225. // isdbt_gpio_config(true);
  226. #if defined(ISDBT_USE_PMIC)
  227. isdbt_control_pmic_pwr(true);
  228. #endif
  229. if (gpio_is_valid(dt_pdata->isdbt_pwr_en2))
  230. {
  231. gpio_set_value(dt_pdata->isdbt_pwr_en2, 1);
  232. usleep_range(1000, 1000);
  233. }
  234. gpio_set_value(dt_pdata->isdbt_pwr_en, 1);
  235. usleep_range(1000, 1000);
  236. if (gpio_is_valid(dt_pdata->isdbt_rst)) {
  237. gpio_set_value(dt_pdata->isdbt_rst, 1);
  238. usleep_range(1000, 1000);
  239. }
  240. }
  241. static void isdbt_gpio_off(void)
  242. {
  243. DPRINTK("isdbt_gpio_off\n");
  244. // isdbt_gpio_config(false);
  245. #if defined(ISDBT_USE_PMIC)
  246. isdbt_control_pmic_pwr(false);
  247. #endif
  248. gpio_set_value(dt_pdata->isdbt_pwr_en, 0);
  249. usleep_range(1000, 1000);
  250. if (gpio_is_valid(dt_pdata->isdbt_pwr_en2)) {
  251. gpio_set_value(dt_pdata->isdbt_pwr_en2, 0);
  252. usleep_range(1000, 1000);
  253. }
  254. if (gpio_is_valid(dt_pdata->isdbt_rst)) {
  255. gpio_set_value(dt_pdata->isdbt_rst, 0);
  256. }
  257. }
  258. bool isdbt_power_off(void)
  259. {
  260. DPRINTK("%s : isdbt_power_off(%d)\n", __func__, isdbt_pwr_on);
  261. if (isdbt_pwr_on) {
  262. (*isdbtdrv_func->power_off)();
  263. #ifdef ISDBT_WAKE_LOCK_ENABLE
  264. wake_unlock(&isdbt_wlock);
  265. #if defined(CONFIG_MTV_QUALCOMM)
  266. pm_qos_update_request(&isdbt_pm_qos_req, PM_QOS_DEFAULT_VALUE);
  267. #endif
  268. #endif
  269. isdbt_pwr_on = false;
  270. }
  271. return true;
  272. }
  273. int isdbt_power_on(unsigned long arg)
  274. {
  275. int ret;
  276. ret = (*isdbtdrv_func->power_on)(arg);
  277. #ifdef ISDBT_WAKE_LOCK_ENABLE
  278. #if defined(CONFIG_MTV_QUALCOMM)
  279. pm_qos_update_request(&isdbt_pm_qos_req,
  280. msm_cpuidle_get_deep_idle_latency());
  281. #endif
  282. wake_lock(&isdbt_wlock);
  283. #endif
  284. if (ret == 0)
  285. isdbt_pwr_on = true;
  286. else
  287. isdbt_pwr_on = false;
  288. DPRINTK("%s : ret(%d)\n", __func__, isdbt_pwr_on);
  289. return ret;
  290. }
  291. bool isdbt_control_irq(bool set)
  292. {
  293. bool ret = true;
  294. int irq_ret;
  295. DPRINTK("isdbt_control_irq\n");
  296. if (!gpio_is_valid(dt_pdata->isdbt_irq))
  297. return false;
  298. if (set) {
  299. irq_ret = request_threaded_irq(gpio_to_irq(dt_pdata->isdbt_irq), NULL,
  300. isdbtdrv_func->irq_handler,
  301. #if defined(CONFIG_MTV_FC8300) || defined(CONFIG_MTV_FC8150)
  302. IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_ONESHOT,
  303. #elif defined(CONFIG_MTV_MTV222) || defined(CONFIG_MTV_MTV23x)
  304. IRQF_DISABLED | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
  305. #endif
  306. ISDBT_DEV_NAME, NULL);
  307. if (irq_ret < 0) {
  308. DPRINTK("request_irq failed !! \r\n");
  309. ret = false;
  310. }
  311. } else {
  312. free_irq(gpio_to_irq(dt_pdata->isdbt_irq), NULL);
  313. }
  314. return ret;
  315. }
  316. void isdbt_control_gpio(bool poweron)
  317. {
  318. if (poweron)
  319. isdbt_gpio_on();
  320. else
  321. isdbt_gpio_off();
  322. }
  323. static ssize_t isdbt_read(struct file *filp, char *buf, size_t count, loff_t *pos)
  324. {
  325. int ret = -EFAULT;
  326. // DPRINTK("isdbt_read\n");
  327. if (isdbtdrv_func->read)
  328. ret = (*isdbtdrv_func->read)(filp, buf, count, pos);
  329. else
  330. ret = 0;
  331. return ret;
  332. }
  333. static long isdbt_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  334. {
  335. int ret = -EFAULT;
  336. if (isdbtdrv_func->ioctl)
  337. ret = (*isdbtdrv_func->ioctl)(filp, cmd, arg);
  338. return ret;
  339. }
  340. static int isdbt_mmap(struct file *filp, struct vm_area_struct *vma)
  341. {
  342. int ret = -EFAULT;
  343. if (isdbtdrv_func->mmap)
  344. ret = (*isdbtdrv_func->mmap)(filp, vma);
  345. return ret;
  346. }
  347. static int isdbt_release(struct inode *inode, struct file *filp)
  348. {
  349. int ret = -EFAULT;
  350. DPRINTK("isdbt_release\n");
  351. if (isdbtdrv_func->release)
  352. ret = (*isdbtdrv_func->release)(inode, filp);
  353. isdbt_power_off();
  354. isdbt_gpio_config(false);
  355. isdbt_control_irq(false);
  356. return 0;
  357. }
  358. static int isdbt_open(struct inode *inode, struct file *filp)
  359. {
  360. int ret = -EFAULT;
  361. DPRINTK("isdbt_open\n");
  362. isdbt_gpio_config(true);
  363. isdbt_control_irq(true);
  364. if (isdbtdrv_func->open)
  365. ret = (*isdbtdrv_func->open)(inode, filp);
  366. else
  367. ret = 0;
  368. return ret;
  369. }
  370. static const struct file_operations isdbt_ctl_fops = {
  371. .owner = THIS_MODULE,
  372. .open = isdbt_open,
  373. .read = isdbt_read,
  374. .unlocked_ioctl = isdbt_ioctl,
  375. .mmap = isdbt_mmap,
  376. .release = isdbt_release,
  377. .llseek = no_llseek,
  378. };
  379. static bool get_isdbt_dt_pdata(struct device *dev)
  380. {
  381. dt_pdata = devm_kzalloc(dev, sizeof(struct isdbt_dt_platform_data), GFP_KERNEL);
  382. if (!dt_pdata) {
  383. DPRINTK("could not allocate memory for platform data\n");
  384. goto err;
  385. }
  386. if(dev->of_node)
  387. {
  388. dt_pdata->isdbt_pwr_en = of_get_named_gpio(dev->of_node, "isdbt_pwr_en", 0);
  389. if (dt_pdata->isdbt_pwr_en < 0) {
  390. DPRINTK("can not find the isdbt_pwr_en\n");
  391. goto alloc_err;
  392. }
  393. dt_pdata->isdbt_pwr_en2 = of_get_named_gpio(dev->of_node, "isdbt_pwr_en2", 0);
  394. if (dt_pdata->isdbt_pwr_en2 < 0) {
  395. DPRINTK("can not find the isdbt_pwr_en2\n");
  396. //goto alloc_err;
  397. }
  398. dt_pdata->isdbt_rst = of_get_named_gpio(dev->of_node, "isdbt_rst", 0);
  399. if (dt_pdata->isdbt_rst < 0) {
  400. DPRINTK("can not find the isdbt_rst\n");
  401. //goto alloc_err;
  402. }
  403. dt_pdata->isdbt_irq = of_get_named_gpio(dev->of_node, "isdbt_irq", 0);
  404. if (dt_pdata->isdbt_irq < 0) {
  405. DPRINTK("can not find the isdbt_irq\n");
  406. goto alloc_err;
  407. }
  408. dt_pdata->isdbt_spi_mosi = of_get_named_gpio(dev->of_node, "isdbt_spi_mosi", 0);
  409. if (dt_pdata->isdbt_spi_mosi < 0) {
  410. DPRINTK("can not find the isdbt_spi_mosi\n");
  411. goto alloc_err;
  412. }
  413. dt_pdata->isdbt_spi_miso = of_get_named_gpio(dev->of_node, "isdbt_spi_miso", 0);
  414. if (dt_pdata->isdbt_spi_miso < 0) {
  415. DPRINTK("can not find the isdbt_spi_miso\n");
  416. goto alloc_err;
  417. }
  418. dt_pdata->isdbt_spi_cs = of_get_named_gpio(dev->of_node, "isdbt_spi_cs", 0);
  419. if (dt_pdata->isdbt_spi_cs < 0) {
  420. DPRINTK("can not find the isdbt_spi_cs\n");
  421. goto alloc_err;
  422. }
  423. dt_pdata->isdbt_spi_clk = of_get_named_gpio(dev->of_node, "isdbt_spi_clk", 0);
  424. if (dt_pdata->isdbt_spi_clk < 0) {
  425. DPRINTK("can not find the isdbt_spi_clk\n");
  426. goto alloc_err;
  427. }
  428. }
  429. else {
  430. DPRINTK("could find device tree\n");
  431. dt_pdata->isdbt_pwr_en = convert_gpio(ISDBT_PWR_EN);
  432. dt_pdata->isdbt_pwr_en2 = convert_gpio(ISDBT_PWR_EN2);
  433. dt_pdata->isdbt_rst = convert_gpio(ISDBT_RST);
  434. dt_pdata->isdbt_irq = convert_gpio(ISDBT_INT);
  435. dt_pdata->isdbt_spi_mosi = convert_gpio(ISDBT_SPI_MOSI);
  436. dt_pdata->isdbt_spi_miso = convert_gpio(ISDBT_SPI_MISO);
  437. dt_pdata->isdbt_spi_cs = convert_gpio(ISDBT_SPI_CS);
  438. dt_pdata->isdbt_spi_clk = convert_gpio(ISDBT_SPI_CLK);
  439. }
  440. return true;
  441. alloc_err:
  442. devm_kfree(dev, dt_pdata);
  443. err:
  444. return false;
  445. }
  446. /*
  447. * isdbt_gpio_request
  448. * @ return value : It returns zero on success, else an error.
  449. */
  450. static int isdbt_gpio_request(void)
  451. {
  452. int err = 0;
  453. /* gpio for isdbt_pwr_en */
  454. err = gpio_request(dt_pdata->isdbt_pwr_en, "isdbt_pwr_en");
  455. if (err) {
  456. DPRINTK("isdbt_pwr_en: gpio request failed\n");
  457. goto out;
  458. }
  459. /* gpio for isdbt_pwr_en2 */
  460. if (gpio_is_valid(dt_pdata->isdbt_pwr_en2))
  461. {
  462. err = gpio_request(dt_pdata->isdbt_pwr_en2, "isdbt_pwr_en2");
  463. if (err) {
  464. DPRINTK("isdbt_pwr_en2: gpio request failed\n");
  465. goto out;
  466. }
  467. }
  468. /* gpio for isdbt_rst */
  469. if (gpio_is_valid(dt_pdata->isdbt_rst))
  470. {
  471. err = gpio_request(dt_pdata->isdbt_rst, "isdbt_rst");
  472. if (err) {
  473. DPRINTK("isdbt_rst: gpio request failed\n");
  474. goto out;
  475. }
  476. }
  477. /* gpio for isdbt_irq */
  478. err = gpio_request(dt_pdata->isdbt_irq, "isdbt_irq");
  479. if (err) {
  480. DPRINTK("isdbt_irq: gpio request failed\n");
  481. goto out;
  482. }
  483. out:
  484. return err;
  485. }
  486. static struct isdbt_drv_func *isdbt_get_drv_func(void)
  487. {
  488. struct isdbt_drv_func * (*func)(void);
  489. #if defined(CONFIG_MTV_FC8150)
  490. func = fc8150_drv_func;
  491. #elif defined(CONFIG_MTV_FC8300)
  492. func = fc8300_drv_func;
  493. #elif defined(CONFIG_MTV_MTV222)
  494. func = mtv222_drv_func;
  495. #elif defined(CONFIG_MTV_MTV23x)
  496. func = mtv23x_drv_func;
  497. #else
  498. #error "an unsupported ISDBT driver!!!"
  499. #endif
  500. return func();
  501. }
  502. static int isdbt_probe(struct platform_device *pdev)
  503. {
  504. int ret = 0;
  505. int result = 0;
  506. DPRINTK("isdbt_probe\n");
  507. result = get_isdbt_dt_pdata(&pdev->dev);
  508. if (!result) {
  509. DPRINTK("isdbt_dt_pdata is NULL.\n");
  510. return -ENODEV;
  511. }
  512. result = isdbt_gpio_request();
  513. if (result) {
  514. DPRINTK("can't request gpio. please check the isdbt_gpio_request()");
  515. return -ENODEV;
  516. }
  517. isdbt_gpio_config(false);
  518. isdbt_spi_init();
  519. isdbtdrv_func = isdbt_get_drv_func();
  520. if (isdbtdrv_func->probe) {
  521. if ((*isdbtdrv_func->probe)() != 0) {
  522. // isdbt_exit_bus();
  523. ret = -EFAULT;
  524. }
  525. } else {
  526. pr_err("%s : isdbtdrv_func is NULL.\n", __func__);
  527. // isdbt_exit_bus();
  528. ret = -EFAULT;
  529. }
  530. #ifdef ISDBT_WAKE_LOCK_ENABLE
  531. #if defined(CONFIG_MTV_QUALCOMM)
  532. pm_qos_add_request(&isdbt_pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
  533. PM_QOS_DEFAULT_VALUE);
  534. #endif
  535. wake_lock_init(&isdbt_wlock, WAKE_LOCK_SUSPEND, "isdbt_wlock");
  536. #endif
  537. return ret;
  538. }
  539. static int isdbt_remove(struct platform_device *pdev)
  540. {
  541. int ret = 0;
  542. DPRINTK("isdbt_remove!\n");
  543. #ifdef ISDBT_WAKE_LOCK_ENABLE
  544. #if defined(CONFIG_MTV_QUALCOMM)
  545. pm_qos_remove_request(&isdbt_pm_qos_req);
  546. #endif
  547. wake_lock_destroy(&isdbt_wlock);
  548. #endif
  549. if (isdbtdrv_func->remove)
  550. ret = isdbtdrv_func->remove();
  551. // isdbt_gpio_config(false);
  552. return 0;
  553. }
  554. static int isdbt_suspend(struct platform_device *pdev, pm_message_t mesg)
  555. {
  556. return 0;
  557. }
  558. static int isdbt_resume(struct platform_device *pdev)
  559. {
  560. return 0;
  561. }
  562. #ifdef ISDBT_DEVICE_TREE
  563. static const struct of_device_id isdbt_match_table[] = {
  564. { .compatible = "isdbt_pdata",
  565. },
  566. {}
  567. };
  568. #endif
  569. static struct platform_driver isdbt_driver = {
  570. .probe = isdbt_probe,
  571. .remove = isdbt_remove,
  572. .suspend = isdbt_suspend,
  573. .resume = isdbt_resume,
  574. .driver = {
  575. .owner = THIS_MODULE,
  576. .name = "isdbt",
  577. #ifdef ISDBT_DEVICE_TREE
  578. .of_match_table = isdbt_match_table,
  579. #endif
  580. },
  581. };
  582. static int __init isdbt_init(void)
  583. {
  584. int ret;
  585. struct device *isdbt_dev;
  586. DPRINTK("Module init\n");
  587. ret = register_chrdev(ISDBT_DEV_MAJOR, ISDBT_DEV_NAME, &isdbt_ctl_fops);
  588. if (ret < 0) {
  589. DPRINTK("Failed to register chrdev\n");
  590. return ret;
  591. }
  592. isdbt_class = class_create(THIS_MODULE, ISDBT_DEV_NAME);
  593. if (IS_ERR(isdbt_class)) {
  594. DPRINTK("class_create failed!\n");
  595. ret = -EFAULT;
  596. goto unreg_chrdev;
  597. }
  598. isdbt_dev = device_create(isdbt_class, NULL,
  599. MKDEV(ISDBT_DEV_MAJOR, ISDBT_DEV_MINOR),
  600. NULL, ISDBT_DEV_NAME);
  601. if (IS_ERR(isdbt_dev)) {
  602. ret = -EFAULT;
  603. DPRINTK("device_create failed!\n");
  604. goto destory_class;
  605. }
  606. ret = platform_driver_register(&isdbt_driver);
  607. if (ret) {
  608. DPRINTK("platform_driver_register failed!\n");
  609. goto destory_device;
  610. }
  611. return 0;
  612. destory_device:
  613. device_destroy(isdbt_class, MKDEV(ISDBT_DEV_MAJOR, ISDBT_DEV_MINOR));
  614. destory_class:
  615. class_destroy(isdbt_class);
  616. unreg_chrdev:
  617. unregister_chrdev(ISDBT_DEV_MAJOR, ISDBT_DEV_NAME);
  618. return ret;
  619. }
  620. static void __exit isdbt_exit(void)
  621. {
  622. DPRINTK("Module exit\n");
  623. platform_driver_unregister(&isdbt_driver);
  624. isdbt_spi_exit();
  625. device_destroy(isdbt_class, MKDEV(ISDBT_DEV_MAJOR, ISDBT_DEV_MINOR));
  626. class_destroy(isdbt_class);
  627. unregister_chrdev(ISDBT_DEV_MAJOR, ISDBT_DEV_NAME);
  628. }
  629. module_init(isdbt_init);
  630. module_exit(isdbt_exit);
  631. MODULE_AUTHOR("Samsung");
  632. MODULE_DESCRIPTION("ISDBT driver");
  633. MODULE_LICENSE("GPL v2");