2758e8af1375401e15c469254745fe2effc44486
[linux-3.10.git] / drivers / misc / tegra-cec / tegra_cec.c
1 /*
2  * drivers/misc/tegra-cec/tegra_cec.c
3  *
4  * Copyright (c) 2012-2014, NVIDIA CORPORATION.  All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #include <linux/module.h>
20 #include <linux/kernel.h>
21 #include <linux/err.h>
22 #include <linux/errno.h>
23 #include <linux/interrupt.h>
24 #include <linux/slab.h>
25 #include <linux/io.h>
26 #include <linux/clk.h>
27 #include <linux/delay.h>
28 #include <linux/workqueue.h>
29 #include <linux/ktime.h>
30 #include <linux/wait.h>
31 #include <linux/sched.h>
32 #include <linux/fs.h>
33 #include <linux/uaccess.h>
34
35 #include <linux/platform_device.h>
36 #include <linux/miscdevice.h>
37 #include <linux/clk/tegra.h>
38 #include <linux/of.h>
39
40 #include "tegra_cec.h"
41
42 static ssize_t cec_logical_addr_store(struct device *dev,
43                 struct device_attribute *attr, const char *buf, size_t count);
44
45 static ssize_t cec_logical_addr_show(struct device *dev,
46                 struct device_attribute *attr, char *buf);
47
48 static DEVICE_ATTR(cec_logical_addr_config, S_IWUSR | S_IRUGO,
49                 cec_logical_addr_show, cec_logical_addr_store);
50
51 static int tegra_cec_open(struct inode *inode, struct file *file)
52 {
53         struct miscdevice *miscdev = file->private_data;
54         struct tegra_cec *cec = container_of(miscdev,
55                 struct tegra_cec, misc_dev);
56         int ret = 0;
57
58         dev_dbg(cec->dev, "%s\n", __func__);
59
60         ret = wait_event_interruptible(cec->init_waitq,
61             atomic_read(&cec->init_done) == 1);
62         if (ret)
63                 return ret;
64         file->private_data = cec;
65
66         return ret;
67 }
68
69 static int tegra_cec_release(struct inode *inode, struct file *file)
70 {
71         struct tegra_cec *cec = file->private_data;
72
73         dev_dbg(cec->dev, "%s\n", __func__);
74
75         return 0;
76 }
77
78 static inline void tegra_cec_native_tx(const struct tegra_cec *cec, u32 block)
79 {
80         writel(block, cec->cec_base + TEGRA_CEC_TX_REGISTER);
81         writel(TEGRA_CEC_INT_STAT_TX_REGISTER_EMPTY,
82                 cec->cec_base + TEGRA_CEC_INT_STAT);
83 }
84
85 static
86 int tegra_cec_native_write_l(struct tegra_cec *cec, const u8 *buf, size_t cnt)
87 {
88         int ret;
89         size_t i;
90         u32 start, mode, eom;
91         u32 mask;
92
93         /*
94          * In case previous transmission was interrupted by signal,
95          *  driver will try to complete the frame anyway.  However,
96          *  this means we have to wait for it to finish before beginning
97          *  subsequent transmission.
98          */
99         ret = wait_event_interruptible(cec->tx_waitq, cec->tx_wake == 1);
100         if (ret)
101                 return ret;
102
103         mode = TEGRA_CEC_LADDR_MODE(buf[0]) << TEGRA_CEC_TX_REG_ADDR_MODE_SHIFT;
104
105         cec->tx_wake = 0;
106         cec->tx_error = 0;
107         cec->tx_buf_cur = 0;
108         cec->tx_buf_cnt = cnt;
109
110         for (i = 0; i < cnt; i++) {
111                 start = i == 0 ? (1 << TEGRA_CEC_TX_REG_START_BIT_SHIFT) : 0;
112                 eom   = i == cnt-1 ? (1 << TEGRA_CEC_TX_REG_EOM_SHIFT) : 0;
113                 cec->tx_buf[i] = start | mode | eom | buf[i];
114         }
115
116         mask = readl(cec->cec_base + TEGRA_CEC_INT_MASK);
117         writel(mask | TEGRA_CEC_INT_MASK_TX_REGISTER_EMPTY,
118                 cec->cec_base + TEGRA_CEC_INT_MASK);
119
120         ret = wait_event_interruptible(cec->tx_waitq, cec->tx_wake == 1);
121         if (!ret)
122                 ret = cec->tx_error;
123
124         return ret;
125 }
126
127 static ssize_t tegra_cec_write(struct file *file, const char __user *buf,
128         size_t count, loff_t *ppos)
129 {
130         u8 tx_buf[TEGRA_CEC_FRAME_MAX_LENGTH];
131         struct tegra_cec *cec = file->private_data;
132         ssize_t ret;
133
134         if (count == 0 || count > TEGRA_CEC_FRAME_MAX_LENGTH)
135                 return -EMSGSIZE;
136
137         ret = wait_event_interruptible(cec->init_waitq,
138             atomic_read(&cec->init_done) == 1);
139         if (ret)
140                 return ret;
141
142         if (copy_from_user(tx_buf, buf, count))
143                 return -EFAULT;
144
145         mutex_lock(&cec->tx_lock);
146         ret = tegra_cec_native_write_l(cec, tx_buf, count);
147         mutex_unlock(&cec->tx_lock);
148         if (ret)
149                 return ret;
150         else
151                 return count;
152 }
153
154 static ssize_t tegra_cec_read(struct file *file, char  __user *buffer,
155         size_t count, loff_t *ppos)
156 {
157         struct tegra_cec *cec = file->private_data;
158         ssize_t ret;
159
160         count = sizeof(cec->rx_buffer);
161
162         ret = wait_event_interruptible(cec->init_waitq,
163             atomic_read(&cec->init_done) == 1);
164         if (ret)
165                 return ret;
166
167         if (cec->rx_wake == 0)
168                 if (file->f_flags & O_NONBLOCK)
169                         return -EAGAIN;
170
171         ret = wait_event_interruptible(cec->rx_waitq, cec->rx_wake == 1);
172         if (ret)
173                 return ret;
174
175         if (copy_to_user(buffer, &(cec->rx_buffer), count))
176                 return -EFAULT;
177
178         cec->rx_buffer = 0x0;
179         cec->rx_wake = 0;
180         return count;
181 }
182
183 static inline void tegra_cec_error_recovery(struct tegra_cec *cec)
184 {
185         u32 hw_ctrl;
186
187         hw_ctrl = readl(cec->cec_base + TEGRA_CEC_HW_CONTROL);
188         writel(0x0, cec->cec_base + TEGRA_CEC_HW_CONTROL);
189         writel(0xFFFFFFFF, cec->cec_base + TEGRA_CEC_INT_STAT);
190         writel(hw_ctrl, cec->cec_base + TEGRA_CEC_HW_CONTROL);
191 }
192
193 static irqreturn_t tegra_cec_irq_handler(int irq, void *data)
194 {
195         struct device *dev = data;
196         struct tegra_cec *cec = dev_get_drvdata(dev);
197         u32 status, mask;
198
199         status = readl(cec->cec_base + TEGRA_CEC_INT_STAT);
200         mask = readl(cec->cec_base + TEGRA_CEC_INT_MASK);
201
202         status &= mask;
203
204         if (!status)
205                 goto out;
206
207         if (status & TEGRA_CEC_INT_STAT_TX_REGISTER_UNDERRUN) {
208                 dev_err(dev, "tegra_cec: TX underrun, interrupt timing issue!\n");
209
210                 tegra_cec_error_recovery(cec);
211                 writel(mask & ~TEGRA_CEC_INT_MASK_TX_REGISTER_EMPTY,
212                         cec->cec_base + TEGRA_CEC_INT_MASK);
213
214                 cec->tx_error = -EIO;
215                 cec->tx_wake = 1;
216
217                 wake_up_interruptible(&cec->tx_waitq);
218
219                 goto out;
220         } else if ((status & TEGRA_CEC_INT_STAT_TX_ARBITRATION_FAILED) ||
221                    (status & TEGRA_CEC_INT_STAT_TX_BUS_ANOMALY_DETECTED)) {
222                 tegra_cec_error_recovery(cec);
223                 writel(mask & ~TEGRA_CEC_INT_MASK_TX_REGISTER_EMPTY,
224                         cec->cec_base + TEGRA_CEC_INT_MASK);
225
226                 cec->tx_error = -ECOMM;
227                 cec->tx_wake = 1;
228
229                 wake_up_interruptible(&cec->tx_waitq);
230
231                 goto out;
232         } else if (status & TEGRA_CEC_INT_STAT_TX_FRAME_TRANSMITTED) {
233                 writel((TEGRA_CEC_INT_STAT_TX_FRAME_TRANSMITTED),
234                         cec->cec_base + TEGRA_CEC_INT_STAT);
235
236                 if (status & TEGRA_CEC_INT_STAT_TX_FRAME_OR_BLOCK_NAKD) {
237                         tegra_cec_error_recovery(cec);
238
239                         cec->tx_error = TEGRA_CEC_LADDR_MODE(cec->tx_buf[0]) ?
240                                         -ECONNRESET : -EHOSTUNREACH;
241                 }
242                 cec->tx_wake = 1;
243
244                 wake_up_interruptible(&cec->tx_waitq);
245
246                 goto out;
247         } else if (status & TEGRA_CEC_INT_STAT_TX_FRAME_OR_BLOCK_NAKD)
248                 dev_warn(dev, "tegra_cec: TX NAKed on the fly!\n");
249
250         if (status & TEGRA_CEC_INT_STAT_TX_REGISTER_EMPTY) {
251                 if (cec->tx_buf_cur == cec->tx_buf_cnt)
252                         writel(mask & ~TEGRA_CEC_INT_MASK_TX_REGISTER_EMPTY,
253                                 cec->cec_base + TEGRA_CEC_INT_MASK);
254                 else
255                         tegra_cec_native_tx(cec,
256                                 cec->tx_buf[cec->tx_buf_cur++]);
257         }
258
259         if (status & (TEGRA_CEC_INT_STAT_RX_REGISTER_OVERRUN |
260                 TEGRA_CEC_INT_STAT_RX_BUS_ANOMALY_DETECTED |
261                 TEGRA_CEC_INT_STAT_RX_START_BIT_DETECTED |
262                 TEGRA_CEC_INT_STAT_RX_BUS_ERROR_DETECTED)) {
263                 writel((TEGRA_CEC_INT_STAT_RX_REGISTER_OVERRUN |
264                         TEGRA_CEC_INT_STAT_RX_BUS_ANOMALY_DETECTED |
265                         TEGRA_CEC_INT_STAT_RX_START_BIT_DETECTED |
266                         TEGRA_CEC_INT_STAT_RX_BUS_ERROR_DETECTED),
267                         cec->cec_base + TEGRA_CEC_INT_STAT);
268         } else if (status & TEGRA_CEC_INT_STAT_RX_REGISTER_FULL) {
269                 writel(TEGRA_CEC_INT_STAT_RX_REGISTER_FULL,
270                         cec->cec_base + TEGRA_CEC_INT_STAT);
271                 cec->rx_buffer = readw(cec->cec_base + TEGRA_CEC_RX_REGISTER);
272                 cec->rx_wake = 1;
273                 wake_up_interruptible(&cec->rx_waitq);
274         }
275
276 out:
277         return IRQ_HANDLED;
278 }
279
280 static const struct file_operations tegra_cec_fops = {
281         .owner = THIS_MODULE,
282         .open = tegra_cec_open,
283         .release = tegra_cec_release,
284         .read = tegra_cec_read,
285         .write = tegra_cec_write,
286 };
287
288 static void tegra_cec_init(struct tegra_cec *cec)
289 {
290         cec->rx_wake = 0;
291         cec->tx_wake = 1;
292         cec->tx_buf_cnt = 0;
293         cec->tx_buf_cur = 0;
294         cec->tx_error = 0;
295
296         dev_notice(cec->dev, "%s started\n", __func__);
297
298         writel(0x00, cec->cec_base + TEGRA_CEC_HW_CONTROL);
299         writel(0x00, cec->cec_base + TEGRA_CEC_INT_MASK);
300         writel(0xffffffff, cec->cec_base + TEGRA_CEC_INT_STAT);
301         msleep(1000);
302
303         writel(0x00, cec->cec_base + TEGRA_CEC_SW_CONTROL);
304
305         cec->logical_addr = TEGRA_CEC_HWCTRL_RX_LADDR_UNREG;
306         writel(TEGRA_CEC_HWCTRL_RX_LADDR(cec->logical_addr) |
307                 TEGRA_CEC_HWCTRL_TX_NAK_MODE |
308                 TEGRA_CEC_HWCTRL_TX_RX_MODE,
309                 cec->cec_base + TEGRA_CEC_HW_CONTROL);
310
311         writel((1U << 31) | 0x20, cec->cec_base + TEGRA_CEC_INPUT_FILTER);
312
313         writel((0x7a << TEGRA_CEC_RX_TIMING_0_RX_START_BIT_MAX_LO_TIME_MASK) |
314            (0x6d << TEGRA_CEC_RX_TIMING_0_RX_START_BIT_MIN_LO_TIME_MASK) |
315            (0x93 << TEGRA_CEC_RX_TIMING_0_RX_START_BIT_MAX_DURATION_MASK) |
316            (0x86 << TEGRA_CEC_RX_TIMING_0_RX_START_BIT_MIN_DURATION_MASK),
317            cec->cec_base + TEGRA_CEC_RX_TIMING_0);
318
319         writel((0x35 << TEGRA_CEC_RX_TIMING_1_RX_DATA_BIT_MAX_LO_TIME_MASK) |
320            (0x21 << TEGRA_CEC_RX_TIMING_1_RX_DATA_BIT_SAMPLE_TIME_MASK) |
321            (0x56 << TEGRA_CEC_RX_TIMING_1_RX_DATA_BIT_MAX_DURATION_MASK) |
322            (0x40 << TEGRA_CEC_RX_TIMING_1_RX_DATA_BIT_MIN_DURATION_MASK),
323            cec->cec_base + TEGRA_CEC_RX_TIMING_1);
324
325         writel((0x50 << TEGRA_CEC_RX_TIMING_2_RX_END_OF_BLOCK_TIME_MASK),
326            cec->cec_base + TEGRA_CEC_RX_TIMING_2);
327
328         writel((0x74 << TEGRA_CEC_TX_TIMING_0_TX_START_BIT_LO_TIME_MASK) |
329            (0x8d << TEGRA_CEC_TX_TIMING_0_TX_START_BIT_DURATION_MASK) |
330            (0x08 << TEGRA_CEC_TX_TIMING_0_TX_BUS_XITION_TIME_MASK) |
331            (0x71 << TEGRA_CEC_TX_TIMING_0_TX_BUS_ERROR_LO_TIME_MASK),
332            cec->cec_base + TEGRA_CEC_TX_TIMING_0);
333
334         writel((0x2f << TEGRA_CEC_TX_TIMING_1_TX_LO_DATA_BIT_LO_TIME_MASK) |
335            (0x13 << TEGRA_CEC_TX_TIMING_1_TX_HI_DATA_BIT_LO_TIME_MASK) |
336            (0x4b << TEGRA_CEC_TX_TIMING_1_TX_DATA_BIT_DURATION_MASK) |
337            (0x21 << TEGRA_CEC_TX_TIMING_1_TX_ACK_NAK_BIT_SAMPLE_TIME_MASK),
338            cec->cec_base + TEGRA_CEC_TX_TIMING_1);
339
340         writel((0x07 << TEGRA_CEC_TX_TIMING_2_BUS_IDLE_TIME_ADDITIONAL_FRAME_MASK) |
341            (0x05 << TEGRA_CEC_TX_TIMING_2_BUS_IDLE_TIME_NEW_FRAME_MASK) |
342            (0x03 << TEGRA_CEC_TX_TIMING_2_BUS_IDLE_TIME_RETRY_FRAME_MASK),
343            cec->cec_base + TEGRA_CEC_TX_TIMING_2);
344
345         writel(TEGRA_CEC_INT_MASK_TX_REGISTER_UNDERRUN |
346                 TEGRA_CEC_INT_MASK_TX_FRAME_OR_BLOCK_NAKD |
347                 TEGRA_CEC_INT_MASK_TX_ARBITRATION_FAILED |
348                 TEGRA_CEC_INT_MASK_TX_BUS_ANOMALY_DETECTED |
349                 TEGRA_CEC_INT_MASK_TX_FRAME_TRANSMITTED |
350                 TEGRA_CEC_INT_MASK_RX_REGISTER_FULL |
351                 TEGRA_CEC_INT_MASK_RX_REGISTER_OVERRUN,
352                 cec->cec_base + TEGRA_CEC_INT_MASK);
353
354         atomic_set(&cec->init_done, 1);
355         wake_up_interruptible(&cec->init_waitq);
356
357         dev_notice(cec->dev, "%s Done.\n", __func__);
358 }
359
360 static void tegra_cec_init_worker(struct work_struct *work)
361 {
362         struct tegra_cec *cec = container_of(work, struct tegra_cec, work);
363
364         tegra_cec_init(cec);
365 }
366
367 static ssize_t cec_logical_addr_show(struct device *dev,
368                 struct device_attribute *attr, char *buf)
369 {
370         struct tegra_cec *cec = dev_get_drvdata(dev);
371
372         if (!atomic_read(&cec->init_done))
373                 return -EAGAIN;
374
375         if (buf)
376                 return sprintf(buf, "0x%x\n", (u32)cec->logical_addr);
377         return 1;
378 }
379
380 static ssize_t cec_logical_addr_store(struct device *dev,
381                 struct device_attribute *attr, const char *buf, size_t count)
382 {
383         ssize_t ret;
384         u32 state;
385         u16 addr;
386         struct tegra_cec *cec;
387
388         if (!buf || !count)
389                 return -EINVAL;
390
391         cec = dev_get_drvdata(dev);
392         if (!atomic_read(&cec->init_done))
393                 return -EAGAIN;
394
395         ret = kstrtou16(buf, 0, &addr);
396         if (ret)
397                 return ret;
398
399
400         dev_info(dev, "tegra_cec: set logical address: %x\n", (u32)addr);
401         cec->logical_addr = addr;
402         state = readl(cec->cec_base + TEGRA_CEC_HW_CONTROL);
403         state &= ~TEGRA_CEC_HWCTRL_RX_LADDR_MASK;
404         state |= TEGRA_CEC_HWCTRL_RX_LADDR(cec->logical_addr);
405         writel(state, cec->cec_base + TEGRA_CEC_HW_CONTROL);
406
407         return count;
408 }
409
410 static int tegra_cec_probe(struct platform_device *pdev)
411 {
412         struct tegra_cec *cec;
413         struct resource *res;
414         int ret = 0;
415
416         cec = devm_kzalloc(&pdev->dev, sizeof(struct tegra_cec), GFP_KERNEL);
417
418         if (!cec)
419                 return -ENOMEM;
420
421         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
422
423         if (!res) {
424                 dev_err(&pdev->dev,
425                     "Unable to allocate resources for device.\n");
426                 ret = -EBUSY;
427                 goto cec_error;
428         }
429
430         if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
431                 pdev->name)) {
432                 dev_err(&pdev->dev,
433                         "Unable to request mem region for device.\n");
434                 ret = -EBUSY;
435                 goto cec_error;
436         }
437
438         cec->tegra_cec_irq = platform_get_irq(pdev, 0);
439
440         if (cec->tegra_cec_irq <= 0) {
441                 ret = -EBUSY;
442                 goto cec_error;
443         }
444
445         cec->cec_base = devm_ioremap_nocache(&pdev->dev, res->start,
446                 resource_size(res));
447
448         if (!cec->cec_base) {
449                 dev_err(&pdev->dev, "Unable to grab IOs for device.\n");
450                 ret = -EBUSY;
451                 goto cec_error;
452         }
453
454         dev_info(&pdev->dev, "dt=%d start=0x%08llX end=0x%08llX irq=%d\n",
455                 (pdev->dev.of_node != NULL),
456                 res->start, res->end,
457                 cec->tegra_cec_irq);
458
459         atomic_set(&cec->init_done, 0);
460         mutex_init(&cec->tx_lock);
461
462         cec->clk = clk_get(&pdev->dev, "cec");
463
464         if (IS_ERR_OR_NULL(cec->clk)) {
465                 dev_err(&pdev->dev, "can't get clock for CEC\n");
466                 ret = -ENOENT;
467                 goto clk_error;
468         }
469
470         clk_enable(cec->clk);
471
472         /* set context info. */
473         cec->dev = &pdev->dev;
474         init_waitqueue_head(&cec->rx_waitq);
475         init_waitqueue_head(&cec->tx_waitq);
476         init_waitqueue_head(&cec->init_waitq);
477
478         platform_set_drvdata(pdev, cec);
479         /* clear out the hardware. */
480
481         INIT_WORK(&cec->work, tegra_cec_init_worker);
482         schedule_work(&cec->work);
483
484         device_init_wakeup(&pdev->dev, 1);
485
486         cec->misc_dev.minor = MISC_DYNAMIC_MINOR;
487         cec->misc_dev.name = TEGRA_CEC_NAME;
488         cec->misc_dev.fops = &tegra_cec_fops;
489         cec->misc_dev.parent = &pdev->dev;
490
491         if (misc_register(&cec->misc_dev)) {
492                 printk(KERN_WARNING "Couldn't register device , %s.\n", TEGRA_CEC_NAME);
493                 goto cec_error;
494         }
495
496         ret = devm_request_irq(&pdev->dev, cec->tegra_cec_irq,
497                 tegra_cec_irq_handler, 0x0, "cec_irq", &pdev->dev);
498
499         if (ret) {
500                 dev_err(&pdev->dev,
501                         "Unable to request interrupt for device (err=%d).\n", ret);
502                 goto cec_error;
503         }
504
505         ret = sysfs_create_file(
506                 &pdev->dev.kobj, &dev_attr_cec_logical_addr_config.attr);
507         dev_info(&pdev->dev, "cec_add_sysfs ret=%d\n", ret);
508         if (ret != 0) {
509                 dev_err(&pdev->dev, "Failed to add sysfs: %d\n", ret);
510                 goto cec_error;
511         }
512
513         dev_notice(&pdev->dev, "probed\n");
514
515         return 0;
516
517 cec_error:
518         clk_disable(cec->clk);
519         clk_put(cec->clk);
520 clk_error:
521         return ret;
522 }
523
524 static int tegra_cec_remove(struct platform_device *pdev)
525 {
526         struct tegra_cec *cec = platform_get_drvdata(pdev);
527
528         clk_disable(cec->clk);
529         clk_put(cec->clk);
530
531         misc_deregister(&cec->misc_dev);
532         cancel_work_sync(&cec->work);
533
534         return 0;
535 }
536
537 #ifdef CONFIG_PM
538 static int tegra_cec_suspend(struct platform_device *pdev, pm_message_t state)
539 {
540         struct tegra_cec *cec = platform_get_drvdata(pdev);
541
542         /* cancel the work queue */
543         cancel_work_sync(&cec->work);
544
545         atomic_set(&cec->init_done, 0);
546
547         clk_disable(cec->clk);
548
549         dev_notice(&pdev->dev, "suspended\n");
550         return 0;
551 }
552
553 static int tegra_cec_resume(struct platform_device *pdev)
554 {
555         struct tegra_cec *cec = platform_get_drvdata(pdev);
556
557         dev_notice(&pdev->dev, "Resuming\n");
558
559         clk_enable(cec->clk);
560         schedule_work(&cec->work);
561
562         return 0;
563 }
564 #endif
565
566 static struct of_device_id tegra_cec_of_match[] = {
567         { .compatible = "nvidia,tegra114-cec", },
568         { .compatible = "nvidia,tegra124-cec", },
569         { .compatible = "nvidia,tegra210-cec", },
570         {},
571 };
572
573 static struct platform_driver tegra_cec_driver = {
574         .driver = {
575                 .name = TEGRA_CEC_NAME,
576                 .owner = THIS_MODULE,
577
578                 .of_match_table = of_match_ptr(tegra_cec_of_match),
579         },
580         .probe = tegra_cec_probe,
581         .remove = tegra_cec_remove,
582
583 #ifdef CONFIG_PM
584         .suspend = tegra_cec_suspend,
585         .resume = tegra_cec_resume,
586 #endif
587 };
588
589 module_platform_driver(tegra_cec_driver);