1
2
3
4
5
6
7
8
9
10
11
12
13
14#include <linux/clk.h>
15#include <linux/delay.h>
16#include <linux/device.h>
17#include <linux/dma-mapping.h>
18#include <linux/i2c.h>
19#include <linux/interrupt.h>
20#include <linux/module.h>
21#include <linux/platform_device.h>
22#include <linux/slab.h>
23#include <linux/sched.h>
24#include <linux/vmalloc.h>
25
26#include <media/v4l2-common.h>
27#include <media/v4l2-device.h>
28#include <media/v4l2-ctrls.h>
29
30#include "iss.h"
31#include "iss_regs.h"
32
33#define ISS_PRINT_REGISTER(iss, name)\
34 dev_dbg(iss->dev, "###ISS " #name "=0x%08x\n", \
35 iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_##name))
36
37static void iss_print_status(struct iss_device *iss)
38{
39 dev_dbg(iss->dev, "-------------ISS HL Register dump-------------\n");
40
41 ISS_PRINT_REGISTER(iss, HL_REVISION);
42 ISS_PRINT_REGISTER(iss, HL_SYSCONFIG);
43 ISS_PRINT_REGISTER(iss, HL_IRQSTATUS(5));
44 ISS_PRINT_REGISTER(iss, HL_IRQENABLE_SET(5));
45 ISS_PRINT_REGISTER(iss, HL_IRQENABLE_CLR(5));
46 ISS_PRINT_REGISTER(iss, CTRL);
47 ISS_PRINT_REGISTER(iss, CLKCTRL);
48 ISS_PRINT_REGISTER(iss, CLKSTAT);
49
50 dev_dbg(iss->dev, "-----------------------------------------------\n");
51}
52
53
54
55
56
57
58
59
60
61
62
63void omap4iss_flush(struct iss_device *iss)
64{
65 iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_REVISION, 0);
66 iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_REVISION);
67}
68
69
70
71
72
73static void omap4iss_isp_enable_interrupts(struct iss_device *iss)
74{
75 static const u32 isp_irq = ISP5_IRQ_OCP_ERR |
76 ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR |
77 ISP5_IRQ_RSZ_FIFO_OVF |
78 ISP5_IRQ_RSZ_INT_DMA |
79 ISP5_IRQ_ISIF_INT(0);
80
81
82 iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQSTATUS(0), isp_irq);
83 iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQENABLE_SET(0),
84 isp_irq);
85}
86
87
88
89
90
91static void omap4iss_isp_disable_interrupts(struct iss_device *iss)
92{
93 iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQENABLE_CLR(0), ~0);
94}
95
96
97
98
99
100static void iss_enable_interrupts(struct iss_device *iss)
101{
102 static const u32 hl_irq = ISS_HL_IRQ_CSIA | ISS_HL_IRQ_CSIB
103 | ISS_HL_IRQ_ISP(0);
104
105
106 iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQSTATUS(5), hl_irq);
107 iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQENABLE_SET(5), hl_irq);
108
109 if (iss->regs[OMAP4_ISS_MEM_ISP_SYS1])
110 omap4iss_isp_enable_interrupts(iss);
111}
112
113
114
115
116
117static void iss_disable_interrupts(struct iss_device *iss)
118{
119 if (iss->regs[OMAP4_ISS_MEM_ISP_SYS1])
120 omap4iss_isp_disable_interrupts(iss);
121
122 iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQENABLE_CLR(5), ~0);
123}
124
125int omap4iss_get_external_info(struct iss_pipeline *pipe,
126 struct media_link *link)
127{
128 struct iss_device *iss =
129 container_of(pipe, struct iss_video, pipe)->iss;
130 struct v4l2_subdev_format fmt;
131 struct v4l2_ctrl *ctrl;
132 int ret;
133
134 if (!pipe->external)
135 return 0;
136
137 if (pipe->external_rate)
138 return 0;
139
140 memset(&fmt, 0, sizeof(fmt));
141
142 fmt.pad = link->source->index;
143 fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
144 ret = v4l2_subdev_call(media_entity_to_v4l2_subdev(link->sink->entity),
145 pad, get_fmt, NULL, &fmt);
146 if (ret < 0)
147 return -EPIPE;
148
149 pipe->external_bpp = omap4iss_video_format_info(fmt.format.code)->bpp;
150
151 ctrl = v4l2_ctrl_find(pipe->external->ctrl_handler,
152 V4L2_CID_PIXEL_RATE);
153 if (ctrl == NULL) {
154 dev_warn(iss->dev, "no pixel rate control in subdev %s\n",
155 pipe->external->name);
156 return -EPIPE;
157 }
158
159 pipe->external_rate = v4l2_ctrl_g_ctrl_int64(ctrl);
160
161 return 0;
162}
163
164
165
166
167
168
169
170
171
172
173void omap4iss_configure_bridge(struct iss_device *iss,
174 enum ipipeif_input_entity input)
175{
176 u32 issctrl_val;
177 u32 isp5ctrl_val;
178
179 issctrl_val = iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_CTRL);
180 issctrl_val &= ~ISS_CTRL_INPUT_SEL_MASK;
181 issctrl_val &= ~ISS_CTRL_CLK_DIV_MASK;
182
183 isp5ctrl_val = iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL);
184
185 switch (input) {
186 case IPIPEIF_INPUT_CSI2A:
187 issctrl_val |= ISS_CTRL_INPUT_SEL_CSI2A;
188 break;
189
190 case IPIPEIF_INPUT_CSI2B:
191 issctrl_val |= ISS_CTRL_INPUT_SEL_CSI2B;
192 break;
193
194 default:
195 return;
196 }
197
198 issctrl_val |= ISS_CTRL_SYNC_DETECT_VS_RAISING;
199
200 isp5ctrl_val |= ISP5_CTRL_VD_PULSE_EXT | ISP5_CTRL_PSYNC_CLK_SEL |
201 ISP5_CTRL_SYNC_ENABLE;
202
203 iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_CTRL, issctrl_val);
204 iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL, isp5ctrl_val);
205}
206
207#ifdef ISS_ISR_DEBUG
208static void iss_isr_dbg(struct iss_device *iss, u32 irqstatus)
209{
210 static const char * const name[] = {
211 "ISP_0",
212 "ISP_1",
213 "ISP_2",
214 "ISP_3",
215 "CSIA",
216 "CSIB",
217 "CCP2_0",
218 "CCP2_1",
219 "CCP2_2",
220 "CCP2_3",
221 "CBUFF",
222 "BTE",
223 "SIMCOP_0",
224 "SIMCOP_1",
225 "SIMCOP_2",
226 "SIMCOP_3",
227 "CCP2_8",
228 "HS_VS",
229 "18",
230 "19",
231 "20",
232 "21",
233 "22",
234 "23",
235 "24",
236 "25",
237 "26",
238 "27",
239 "28",
240 "29",
241 "30",
242 "31",
243 };
244 unsigned int i;
245
246 dev_dbg(iss->dev, "ISS IRQ: ");
247
248 for (i = 0; i < ARRAY_SIZE(name); i++) {
249 if ((1 << i) & irqstatus)
250 pr_cont("%s ", name[i]);
251 }
252 pr_cont("\n");
253}
254
255static void iss_isp_isr_dbg(struct iss_device *iss, u32 irqstatus)
256{
257 static const char * const name[] = {
258 "ISIF_0",
259 "ISIF_1",
260 "ISIF_2",
261 "ISIF_3",
262 "IPIPEREQ",
263 "IPIPELAST_PIX",
264 "IPIPEDMA",
265 "IPIPEBSC",
266 "IPIPEHST",
267 "IPIPEIF",
268 "AEW",
269 "AF",
270 "H3A",
271 "RSZ_REG",
272 "RSZ_LAST_PIX",
273 "RSZ_DMA",
274 "RSZ_CYC_RZA",
275 "RSZ_CYC_RZB",
276 "RSZ_FIFO_OVF",
277 "RSZ_FIFO_IN_BLK_ERR",
278 "20",
279 "21",
280 "RSZ_EOF0",
281 "RSZ_EOF1",
282 "H3A_EOF",
283 "IPIPE_EOF",
284 "26",
285 "IPIPE_DPC_INI",
286 "IPIPE_DPC_RNEW0",
287 "IPIPE_DPC_RNEW1",
288 "30",
289 "OCP_ERR",
290 };
291 unsigned int i;
292
293 dev_dbg(iss->dev, "ISP IRQ: ");
294
295 for (i = 0; i < ARRAY_SIZE(name); i++) {
296 if ((1 << i) & irqstatus)
297 pr_cont("%s ", name[i]);
298 }
299 pr_cont("\n");
300}
301#endif
302
303
304
305
306
307
308
309
310
311
312
313static irqreturn_t iss_isr(int irq, void *_iss)
314{
315 static const u32 ipipeif_events = ISP5_IRQ_IPIPEIF_IRQ |
316 ISP5_IRQ_ISIF_INT(0);
317 static const u32 resizer_events = ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR |
318 ISP5_IRQ_RSZ_FIFO_OVF |
319 ISP5_IRQ_RSZ_INT_DMA;
320 struct iss_device *iss = _iss;
321 u32 irqstatus;
322
323 irqstatus = iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQSTATUS(5));
324 iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQSTATUS(5), irqstatus);
325
326 if (irqstatus & ISS_HL_IRQ_CSIA)
327 omap4iss_csi2_isr(&iss->csi2a);
328
329 if (irqstatus & ISS_HL_IRQ_CSIB)
330 omap4iss_csi2_isr(&iss->csi2b);
331
332 if (irqstatus & ISS_HL_IRQ_ISP(0)) {
333 u32 isp_irqstatus = iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1,
334 ISP5_IRQSTATUS(0));
335 iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQSTATUS(0),
336 isp_irqstatus);
337
338 if (isp_irqstatus & ISP5_IRQ_OCP_ERR)
339 dev_dbg(iss->dev, "ISP5 OCP Error!\n");
340
341 if (isp_irqstatus & ipipeif_events) {
342 omap4iss_ipipeif_isr(&iss->ipipeif,
343 isp_irqstatus & ipipeif_events);
344 }
345
346 if (isp_irqstatus & resizer_events)
347 omap4iss_resizer_isr(&iss->resizer,
348 isp_irqstatus & resizer_events);
349
350#ifdef ISS_ISR_DEBUG
351 iss_isp_isr_dbg(iss, isp_irqstatus);
352#endif
353 }
354
355 omap4iss_flush(iss);
356
357#ifdef ISS_ISR_DEBUG
358 iss_isr_dbg(iss, irqstatus);
359#endif
360
361 return IRQ_HANDLED;
362}
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391static int iss_pipeline_pm_use_count(struct media_entity *entity)
392{
393 struct media_entity_graph graph;
394 int use = 0;
395
396 media_entity_graph_walk_start(&graph, entity);
397
398 while ((entity = media_entity_graph_walk_next(&graph))) {
399 if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
400 use += entity->use_count;
401 }
402
403 return use;
404}
405
406
407
408
409
410
411
412
413
414
415
416
417static int iss_pipeline_pm_power_one(struct media_entity *entity, int change)
418{
419 struct v4l2_subdev *subdev;
420
421 subdev = media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV
422 ? media_entity_to_v4l2_subdev(entity) : NULL;
423
424 if (entity->use_count == 0 && change > 0 && subdev != NULL) {
425 int ret;
426
427 ret = v4l2_subdev_call(subdev, core, s_power, 1);
428 if (ret < 0 && ret != -ENOIOCTLCMD)
429 return ret;
430 }
431
432 entity->use_count += change;
433 WARN_ON(entity->use_count < 0);
434
435 if (entity->use_count == 0 && change < 0 && subdev != NULL)
436 v4l2_subdev_call(subdev, core, s_power, 0);
437
438 return 0;
439}
440
441
442
443
444
445
446
447
448
449
450
451static int iss_pipeline_pm_power(struct media_entity *entity, int change)
452{
453 struct media_entity_graph graph;
454 struct media_entity *first = entity;
455 int ret = 0;
456
457 if (!change)
458 return 0;
459
460 media_entity_graph_walk_start(&graph, entity);
461
462 while (!ret && (entity = media_entity_graph_walk_next(&graph)))
463 if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
464 ret = iss_pipeline_pm_power_one(entity, change);
465
466 if (!ret)
467 return 0;
468
469 media_entity_graph_walk_start(&graph, first);
470
471 while ((first = media_entity_graph_walk_next(&graph))
472 && first != entity)
473 if (media_entity_type(first) != MEDIA_ENT_T_DEVNODE)
474 iss_pipeline_pm_power_one(first, -change);
475
476 return ret;
477}
478
479
480
481
482
483
484
485
486
487
488
489
490
491int omap4iss_pipeline_pm_use(struct media_entity *entity, int use)
492{
493 int change = use ? 1 : -1;
494 int ret;
495
496 mutex_lock(&entity->parent->graph_mutex);
497
498
499 entity->use_count += change;
500 WARN_ON(entity->use_count < 0);
501
502
503 ret = iss_pipeline_pm_power(entity, change);
504 if (ret < 0)
505 entity->use_count -= change;
506
507 mutex_unlock(&entity->parent->graph_mutex);
508
509 return ret;
510}
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525static int iss_pipeline_link_notify(struct media_link *link, u32 flags,
526 unsigned int notification)
527{
528 struct media_entity *source = link->source->entity;
529 struct media_entity *sink = link->sink->entity;
530 int source_use = iss_pipeline_pm_use_count(source);
531 int sink_use = iss_pipeline_pm_use_count(sink);
532 int ret;
533
534 if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH &&
535 !(link->flags & MEDIA_LNK_FL_ENABLED)) {
536
537 iss_pipeline_pm_power(source, -sink_use);
538 iss_pipeline_pm_power(sink, -source_use);
539 return 0;
540 }
541
542 if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH &&
543 (flags & MEDIA_LNK_FL_ENABLED)) {
544 ret = iss_pipeline_pm_power(source, sink_use);
545 if (ret < 0)
546 return ret;
547
548 ret = iss_pipeline_pm_power(sink, source_use);
549 if (ret < 0)
550 iss_pipeline_pm_power(source, -sink_use);
551
552 return ret;
553 }
554
555 return 0;
556}
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573static int iss_pipeline_enable(struct iss_pipeline *pipe,
574 enum iss_pipeline_stream_state mode)
575{
576 struct iss_device *iss = pipe->output->iss;
577 struct media_entity *entity;
578 struct media_pad *pad;
579 struct v4l2_subdev *subdev;
580 unsigned long flags;
581 int ret;
582
583
584
585
586
587
588
589 if (pipe->entities & iss->crashed)
590 return -EIO;
591
592 spin_lock_irqsave(&pipe->lock, flags);
593 pipe->state &= ~(ISS_PIPELINE_IDLE_INPUT | ISS_PIPELINE_IDLE_OUTPUT);
594 spin_unlock_irqrestore(&pipe->lock, flags);
595
596 pipe->do_propagation = false;
597
598 entity = &pipe->output->video.entity;
599 while (1) {
600 pad = &entity->pads[0];
601 if (!(pad->flags & MEDIA_PAD_FL_SINK))
602 break;
603
604 pad = media_entity_remote_pad(pad);
605 if (pad == NULL ||
606 media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
607 break;
608
609 entity = pad->entity;
610 subdev = media_entity_to_v4l2_subdev(entity);
611
612 ret = v4l2_subdev_call(subdev, video, s_stream, mode);
613 if (ret < 0 && ret != -ENOIOCTLCMD)
614 return ret;
615 }
616 iss_print_status(pipe->output->iss);
617 return 0;
618}
619
620
621
622
623
624
625
626
627
628static int iss_pipeline_disable(struct iss_pipeline *pipe)
629{
630 struct iss_device *iss = pipe->output->iss;
631 struct media_entity *entity;
632 struct media_pad *pad;
633 struct v4l2_subdev *subdev;
634 int failure = 0;
635 int ret;
636
637 entity = &pipe->output->video.entity;
638 while (1) {
639 pad = &entity->pads[0];
640 if (!(pad->flags & MEDIA_PAD_FL_SINK))
641 break;
642
643 pad = media_entity_remote_pad(pad);
644 if (pad == NULL ||
645 media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
646 break;
647
648 entity = pad->entity;
649 subdev = media_entity_to_v4l2_subdev(entity);
650
651 ret = v4l2_subdev_call(subdev, video, s_stream, 0);
652 if (ret < 0) {
653 dev_dbg(iss->dev, "%s: module stop timeout.\n",
654 subdev->name);
655
656
657
658
659 iss->crashed |= 1U << subdev->entity.id;
660 failure = -ETIMEDOUT;
661 }
662 }
663
664 return failure;
665}
666
667
668
669
670
671
672
673
674
675
676
677
678
679int omap4iss_pipeline_set_stream(struct iss_pipeline *pipe,
680 enum iss_pipeline_stream_state state)
681{
682 int ret;
683
684 if (state == ISS_PIPELINE_STREAM_STOPPED)
685 ret = iss_pipeline_disable(pipe);
686 else
687 ret = iss_pipeline_enable(pipe, state);
688
689 if (ret == 0 || state == ISS_PIPELINE_STREAM_STOPPED)
690 pipe->stream_state = state;
691
692 return ret;
693}
694
695
696
697
698
699
700
701
702
703
704void omap4iss_pipeline_cancel_stream(struct iss_pipeline *pipe)
705{
706 if (pipe->input)
707 omap4iss_video_cancel_stream(pipe->input);
708 if (pipe->output)
709 omap4iss_video_cancel_stream(pipe->output);
710}
711
712
713
714
715
716
717
718
719
720
721static int iss_pipeline_is_last(struct media_entity *me)
722{
723 struct iss_pipeline *pipe;
724 struct media_pad *pad;
725
726 if (!me->pipe)
727 return 0;
728 pipe = to_iss_pipeline(me);
729 if (pipe->stream_state == ISS_PIPELINE_STREAM_STOPPED)
730 return 0;
731 pad = media_entity_remote_pad(&pipe->output->pad);
732 return pad->entity == me;
733}
734
735static int iss_reset(struct iss_device *iss)
736{
737 unsigned int timeout;
738
739 iss_reg_set(iss, OMAP4_ISS_MEM_TOP, ISS_HL_SYSCONFIG,
740 ISS_HL_SYSCONFIG_SOFTRESET);
741
742 timeout = iss_poll_condition_timeout(
743 !(iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_SYSCONFIG) &
744 ISS_HL_SYSCONFIG_SOFTRESET), 1000, 10, 100);
745 if (timeout) {
746 dev_err(iss->dev, "ISS reset timeout\n");
747 return -ETIMEDOUT;
748 }
749
750 iss->crashed = 0;
751 return 0;
752}
753
754static int iss_isp_reset(struct iss_device *iss)
755{
756 unsigned int timeout;
757
758
759 iss_reg_update(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_SYSCONFIG,
760 ISP5_SYSCONFIG_STANDBYMODE_MASK,
761 ISP5_SYSCONFIG_STANDBYMODE_SMART);
762
763 iss_reg_set(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL, ISP5_CTRL_MSTANDBY);
764
765 timeout = iss_poll_condition_timeout(
766 iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL) &
767 ISP5_CTRL_MSTANDBY_WAIT, 1000000, 1000, 1500);
768 if (timeout) {
769 dev_err(iss->dev, "ISP5 standby timeout\n");
770 return -ETIMEDOUT;
771 }
772
773
774 iss_reg_set(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_SYSCONFIG,
775 ISP5_SYSCONFIG_SOFTRESET);
776
777 timeout = iss_poll_condition_timeout(
778 !(iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_SYSCONFIG) &
779 ISP5_SYSCONFIG_SOFTRESET), 1000000, 1000, 1500);
780 if (timeout) {
781 dev_err(iss->dev, "ISP5 reset timeout\n");
782 return -ETIMEDOUT;
783 }
784
785 return 0;
786}
787
788
789
790
791
792
793
794
795
796
797int omap4iss_module_sync_idle(struct media_entity *me, wait_queue_head_t *wait,
798 atomic_t *stopping)
799{
800 struct iss_pipeline *pipe = to_iss_pipeline(me);
801 struct iss_video *video = pipe->output;
802 unsigned long flags;
803
804 if (pipe->stream_state == ISS_PIPELINE_STREAM_STOPPED ||
805 (pipe->stream_state == ISS_PIPELINE_STREAM_SINGLESHOT &&
806 !iss_pipeline_ready(pipe)))
807 return 0;
808
809
810
811
812
813 atomic_set(stopping, 1);
814 smp_wmb();
815
816
817
818
819
820
821
822
823
824
825 if (!iss_pipeline_is_last(me))
826 return 0;
827
828 spin_lock_irqsave(&video->qlock, flags);
829 if (video->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_UNDERRUN) {
830 spin_unlock_irqrestore(&video->qlock, flags);
831 atomic_set(stopping, 0);
832 smp_wmb();
833 return 0;
834 }
835 spin_unlock_irqrestore(&video->qlock, flags);
836 if (!wait_event_timeout(*wait, !atomic_read(stopping),
837 msecs_to_jiffies(1000))) {
838 atomic_set(stopping, 0);
839 smp_wmb();
840 return -ETIMEDOUT;
841 }
842
843 return 0;
844}
845
846
847
848
849
850
851
852
853
854
855int omap4iss_module_sync_is_stopping(wait_queue_head_t *wait,
856 atomic_t *stopping)
857{
858 if (atomic_cmpxchg(stopping, 1, 0)) {
859 wake_up(wait);
860 return 1;
861 }
862
863 return 0;
864}
865
866
867
868
869
870#define ISS_CLKCTRL_MASK (ISS_CLKCTRL_CSI2_A |\
871 ISS_CLKCTRL_CSI2_B |\
872 ISS_CLKCTRL_ISP)
873
874static int __iss_subclk_update(struct iss_device *iss)
875{
876 u32 clk = 0;
877 int ret = 0, timeout = 1000;
878
879 if (iss->subclk_resources & OMAP4_ISS_SUBCLK_CSI2_A)
880 clk |= ISS_CLKCTRL_CSI2_A;
881
882 if (iss->subclk_resources & OMAP4_ISS_SUBCLK_CSI2_B)
883 clk |= ISS_CLKCTRL_CSI2_B;
884
885 if (iss->subclk_resources & OMAP4_ISS_SUBCLK_ISP)
886 clk |= ISS_CLKCTRL_ISP;
887
888 iss_reg_update(iss, OMAP4_ISS_MEM_TOP, ISS_CLKCTRL,
889 ISS_CLKCTRL_MASK, clk);
890
891
892 while (--timeout > 0) {
893 udelay(1);
894 if ((iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_CLKSTAT) &
895 ISS_CLKCTRL_MASK) == clk)
896 break;
897 }
898
899 if (!timeout)
900 ret = -EBUSY;
901
902 return ret;
903}
904
905int omap4iss_subclk_enable(struct iss_device *iss,
906 enum iss_subclk_resource res)
907{
908 iss->subclk_resources |= res;
909
910 return __iss_subclk_update(iss);
911}
912
913int omap4iss_subclk_disable(struct iss_device *iss,
914 enum iss_subclk_resource res)
915{
916 iss->subclk_resources &= ~res;
917
918 return __iss_subclk_update(iss);
919}
920
921#define ISS_ISP5_CLKCTRL_MASK (ISP5_CTRL_BL_CLK_ENABLE |\
922 ISP5_CTRL_ISIF_CLK_ENABLE |\
923 ISP5_CTRL_H3A_CLK_ENABLE |\
924 ISP5_CTRL_RSZ_CLK_ENABLE |\
925 ISP5_CTRL_IPIPE_CLK_ENABLE |\
926 ISP5_CTRL_IPIPEIF_CLK_ENABLE)
927
928static void __iss_isp_subclk_update(struct iss_device *iss)
929{
930 u32 clk = 0;
931
932 if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_ISIF)
933 clk |= ISP5_CTRL_ISIF_CLK_ENABLE;
934
935 if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_H3A)
936 clk |= ISP5_CTRL_H3A_CLK_ENABLE;
937
938 if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_RSZ)
939 clk |= ISP5_CTRL_RSZ_CLK_ENABLE;
940
941 if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_IPIPE)
942 clk |= ISP5_CTRL_IPIPE_CLK_ENABLE;
943
944 if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_IPIPEIF)
945 clk |= ISP5_CTRL_IPIPEIF_CLK_ENABLE;
946
947 if (clk)
948 clk |= ISP5_CTRL_BL_CLK_ENABLE;
949
950 iss_reg_update(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL,
951 ISS_ISP5_CLKCTRL_MASK, clk);
952}
953
954void omap4iss_isp_subclk_enable(struct iss_device *iss,
955 enum iss_isp_subclk_resource res)
956{
957 iss->isp_subclk_resources |= res;
958
959 __iss_isp_subclk_update(iss);
960}
961
962void omap4iss_isp_subclk_disable(struct iss_device *iss,
963 enum iss_isp_subclk_resource res)
964{
965 iss->isp_subclk_resources &= ~res;
966
967 __iss_isp_subclk_update(iss);
968}
969
970
971
972
973
974
975
976static int iss_enable_clocks(struct iss_device *iss)
977{
978 int ret;
979
980 ret = clk_enable(iss->iss_fck);
981 if (ret) {
982 dev_err(iss->dev, "clk_enable iss_fck failed\n");
983 return ret;
984 }
985
986 ret = clk_enable(iss->iss_ctrlclk);
987 if (ret) {
988 dev_err(iss->dev, "clk_enable iss_ctrlclk failed\n");
989 clk_disable(iss->iss_fck);
990 return ret;
991 }
992
993 return 0;
994}
995
996
997
998
999
1000static void iss_disable_clocks(struct iss_device *iss)
1001{
1002 clk_disable(iss->iss_ctrlclk);
1003 clk_disable(iss->iss_fck);
1004}
1005
1006static int iss_get_clocks(struct iss_device *iss)
1007{
1008 iss->iss_fck = devm_clk_get(iss->dev, "iss_fck");
1009 if (IS_ERR(iss->iss_fck)) {
1010 dev_err(iss->dev, "Unable to get iss_fck clock info\n");
1011 return PTR_ERR(iss->iss_fck);
1012 }
1013
1014 iss->iss_ctrlclk = devm_clk_get(iss->dev, "iss_ctrlclk");
1015 if (IS_ERR(iss->iss_ctrlclk)) {
1016 dev_err(iss->dev, "Unable to get iss_ctrlclk clock info\n");
1017 return PTR_ERR(iss->iss_ctrlclk);
1018 }
1019
1020 return 0;
1021}
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033struct iss_device *omap4iss_get(struct iss_device *iss)
1034{
1035 struct iss_device *__iss = iss;
1036
1037 if (iss == NULL)
1038 return NULL;
1039
1040 mutex_lock(&iss->iss_mutex);
1041 if (iss->ref_count > 0)
1042 goto out;
1043
1044 if (iss_enable_clocks(iss) < 0) {
1045 __iss = NULL;
1046 goto out;
1047 }
1048
1049 iss_enable_interrupts(iss);
1050
1051out:
1052 if (__iss != NULL)
1053 iss->ref_count++;
1054 mutex_unlock(&iss->iss_mutex);
1055
1056 return __iss;
1057}
1058
1059
1060
1061
1062
1063
1064
1065void omap4iss_put(struct iss_device *iss)
1066{
1067 if (iss == NULL)
1068 return;
1069
1070 mutex_lock(&iss->iss_mutex);
1071 BUG_ON(iss->ref_count == 0);
1072 if (--iss->ref_count == 0) {
1073 iss_disable_interrupts(iss);
1074
1075
1076
1077
1078
1079 if (iss->crashed)
1080 iss_reset(iss);
1081 iss_disable_clocks(iss);
1082 }
1083 mutex_unlock(&iss->iss_mutex);
1084}
1085
1086static int iss_map_mem_resource(struct platform_device *pdev,
1087 struct iss_device *iss,
1088 enum iss_mem_resources res)
1089{
1090 struct resource *mem;
1091
1092 mem = platform_get_resource(pdev, IORESOURCE_MEM, res);
1093
1094 iss->regs[res] = devm_ioremap_resource(iss->dev, mem);
1095
1096 return PTR_ERR_OR_ZERO(iss->regs[res]);
1097}
1098
1099static void iss_unregister_entities(struct iss_device *iss)
1100{
1101 omap4iss_resizer_unregister_entities(&iss->resizer);
1102 omap4iss_ipipe_unregister_entities(&iss->ipipe);
1103 omap4iss_ipipeif_unregister_entities(&iss->ipipeif);
1104 omap4iss_csi2_unregister_entities(&iss->csi2a);
1105 omap4iss_csi2_unregister_entities(&iss->csi2b);
1106
1107 v4l2_device_unregister(&iss->v4l2_dev);
1108 media_device_unregister(&iss->media_dev);
1109}
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122static struct v4l2_subdev *
1123iss_register_subdev_group(struct iss_device *iss,
1124 struct iss_subdev_i2c_board_info *board_info)
1125{
1126 struct v4l2_subdev *sensor = NULL;
1127 unsigned int first;
1128
1129 if (board_info->board_info == NULL)
1130 return NULL;
1131
1132 for (first = 1; board_info->board_info; ++board_info, first = 0) {
1133 struct v4l2_subdev *subdev;
1134 struct i2c_adapter *adapter;
1135
1136 adapter = i2c_get_adapter(board_info->i2c_adapter_id);
1137 if (adapter == NULL) {
1138 dev_err(iss->dev,
1139 "%s: Unable to get I2C adapter %d for device %s\n",
1140 __func__, board_info->i2c_adapter_id,
1141 board_info->board_info->type);
1142 continue;
1143 }
1144
1145 subdev = v4l2_i2c_new_subdev_board(&iss->v4l2_dev, adapter,
1146 board_info->board_info, NULL);
1147 if (subdev == NULL) {
1148 dev_err(iss->dev, "%s: Unable to register subdev %s\n",
1149 __func__, board_info->board_info->type);
1150 continue;
1151 }
1152
1153 if (first)
1154 sensor = subdev;
1155 }
1156
1157 return sensor;
1158}
1159
1160static int iss_register_entities(struct iss_device *iss)
1161{
1162 struct iss_platform_data *pdata = iss->pdata;
1163 struct iss_v4l2_subdevs_group *subdevs;
1164 int ret;
1165
1166 iss->media_dev.dev = iss->dev;
1167 strlcpy(iss->media_dev.model, "TI OMAP4 ISS",
1168 sizeof(iss->media_dev.model));
1169 iss->media_dev.hw_revision = iss->revision;
1170 iss->media_dev.link_notify = iss_pipeline_link_notify;
1171 ret = media_device_register(&iss->media_dev);
1172 if (ret < 0) {
1173 dev_err(iss->dev, "%s: Media device registration failed (%d)\n",
1174 __func__, ret);
1175 return ret;
1176 }
1177
1178 iss->v4l2_dev.mdev = &iss->media_dev;
1179 ret = v4l2_device_register(iss->dev, &iss->v4l2_dev);
1180 if (ret < 0) {
1181 dev_err(iss->dev, "%s: V4L2 device registration failed (%d)\n",
1182 __func__, ret);
1183 goto done;
1184 }
1185
1186
1187 ret = omap4iss_csi2_register_entities(&iss->csi2a, &iss->v4l2_dev);
1188 if (ret < 0)
1189 goto done;
1190
1191 ret = omap4iss_csi2_register_entities(&iss->csi2b, &iss->v4l2_dev);
1192 if (ret < 0)
1193 goto done;
1194
1195 ret = omap4iss_ipipeif_register_entities(&iss->ipipeif, &iss->v4l2_dev);
1196 if (ret < 0)
1197 goto done;
1198
1199 ret = omap4iss_ipipe_register_entities(&iss->ipipe, &iss->v4l2_dev);
1200 if (ret < 0)
1201 goto done;
1202
1203 ret = omap4iss_resizer_register_entities(&iss->resizer, &iss->v4l2_dev);
1204 if (ret < 0)
1205 goto done;
1206
1207
1208 for (subdevs = pdata->subdevs; subdevs && subdevs->subdevs; ++subdevs) {
1209 struct v4l2_subdev *sensor;
1210 struct media_entity *input;
1211 unsigned int flags;
1212 unsigned int pad;
1213
1214 sensor = iss_register_subdev_group(iss, subdevs->subdevs);
1215 if (sensor == NULL)
1216 continue;
1217
1218 sensor->host_priv = subdevs;
1219
1220
1221
1222
1223
1224 switch (subdevs->interface) {
1225 case ISS_INTERFACE_CSI2A_PHY1:
1226 input = &iss->csi2a.subdev.entity;
1227 pad = CSI2_PAD_SINK;
1228 flags = MEDIA_LNK_FL_IMMUTABLE
1229 | MEDIA_LNK_FL_ENABLED;
1230 break;
1231
1232 case ISS_INTERFACE_CSI2B_PHY2:
1233 input = &iss->csi2b.subdev.entity;
1234 pad = CSI2_PAD_SINK;
1235 flags = MEDIA_LNK_FL_IMMUTABLE
1236 | MEDIA_LNK_FL_ENABLED;
1237 break;
1238
1239 default:
1240 dev_err(iss->dev, "%s: invalid interface type %u\n",
1241 __func__, subdevs->interface);
1242 ret = -EINVAL;
1243 goto done;
1244 }
1245
1246 ret = media_entity_create_link(&sensor->entity, 0, input, pad,
1247 flags);
1248 if (ret < 0)
1249 goto done;
1250 }
1251
1252 ret = v4l2_device_register_subdev_nodes(&iss->v4l2_dev);
1253
1254done:
1255 if (ret < 0)
1256 iss_unregister_entities(iss);
1257
1258 return ret;
1259}
1260
1261static void iss_cleanup_modules(struct iss_device *iss)
1262{
1263 omap4iss_csi2_cleanup(iss);
1264 omap4iss_ipipeif_cleanup(iss);
1265 omap4iss_ipipe_cleanup(iss);
1266 omap4iss_resizer_cleanup(iss);
1267}
1268
1269static int iss_initialize_modules(struct iss_device *iss)
1270{
1271 int ret;
1272
1273 ret = omap4iss_csiphy_init(iss);
1274 if (ret < 0) {
1275 dev_err(iss->dev, "CSI PHY initialization failed\n");
1276 goto error_csiphy;
1277 }
1278
1279 ret = omap4iss_csi2_init(iss);
1280 if (ret < 0) {
1281 dev_err(iss->dev, "CSI2 initialization failed\n");
1282 goto error_csi2;
1283 }
1284
1285 ret = omap4iss_ipipeif_init(iss);
1286 if (ret < 0) {
1287 dev_err(iss->dev, "ISP IPIPEIF initialization failed\n");
1288 goto error_ipipeif;
1289 }
1290
1291 ret = omap4iss_ipipe_init(iss);
1292 if (ret < 0) {
1293 dev_err(iss->dev, "ISP IPIPE initialization failed\n");
1294 goto error_ipipe;
1295 }
1296
1297 ret = omap4iss_resizer_init(iss);
1298 if (ret < 0) {
1299 dev_err(iss->dev, "ISP RESIZER initialization failed\n");
1300 goto error_resizer;
1301 }
1302
1303
1304 ret = media_entity_create_link(
1305 &iss->csi2a.subdev.entity, CSI2_PAD_SOURCE,
1306 &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0);
1307 if (ret < 0)
1308 goto error_link;
1309
1310 ret = media_entity_create_link(
1311 &iss->csi2b.subdev.entity, CSI2_PAD_SOURCE,
1312 &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0);
1313 if (ret < 0)
1314 goto error_link;
1315
1316 ret = media_entity_create_link(
1317 &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP,
1318 &iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0);
1319 if (ret < 0)
1320 goto error_link;
1321
1322 ret = media_entity_create_link(
1323 &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP,
1324 &iss->ipipe.subdev.entity, IPIPE_PAD_SINK, 0);
1325 if (ret < 0)
1326 goto error_link;
1327
1328 ret = media_entity_create_link(
1329 &iss->ipipe.subdev.entity, IPIPE_PAD_SOURCE_VP,
1330 &iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0);
1331 if (ret < 0)
1332 goto error_link;
1333
1334 return 0;
1335
1336error_link:
1337 omap4iss_resizer_cleanup(iss);
1338error_resizer:
1339 omap4iss_ipipe_cleanup(iss);
1340error_ipipe:
1341 omap4iss_ipipeif_cleanup(iss);
1342error_ipipeif:
1343 omap4iss_csi2_cleanup(iss);
1344error_csi2:
1345error_csiphy:
1346 return ret;
1347}
1348
1349static int iss_probe(struct platform_device *pdev)
1350{
1351 struct iss_platform_data *pdata = pdev->dev.platform_data;
1352 struct iss_device *iss;
1353 unsigned int i;
1354 int ret;
1355
1356 if (pdata == NULL)
1357 return -EINVAL;
1358
1359 iss = devm_kzalloc(&pdev->dev, sizeof(*iss), GFP_KERNEL);
1360 if (!iss) {
1361 dev_err(&pdev->dev, "Could not allocate memory\n");
1362 return -ENOMEM;
1363 }
1364
1365 mutex_init(&iss->iss_mutex);
1366
1367 iss->dev = &pdev->dev;
1368 iss->pdata = pdata;
1369
1370 iss->raw_dmamask = DMA_BIT_MASK(32);
1371 iss->dev->dma_mask = &iss->raw_dmamask;
1372 iss->dev->coherent_dma_mask = DMA_BIT_MASK(32);
1373
1374 platform_set_drvdata(pdev, iss);
1375
1376
1377 ret = iss_map_mem_resource(pdev, iss, OMAP4_ISS_MEM_TOP);
1378 if (ret < 0)
1379 goto error;
1380
1381 ret = iss_get_clocks(iss);
1382 if (ret < 0)
1383 goto error;
1384
1385 if (omap4iss_get(iss) == NULL)
1386 goto error;
1387
1388 ret = iss_reset(iss);
1389 if (ret < 0)
1390 goto error_iss;
1391
1392 iss->revision = iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_REVISION);
1393 dev_info(iss->dev, "Revision %08x found\n", iss->revision);
1394
1395 for (i = 1; i < OMAP4_ISS_MEM_LAST; i++) {
1396 ret = iss_map_mem_resource(pdev, iss, i);
1397 if (ret)
1398 goto error_iss;
1399 }
1400
1401
1402 iss_reg_update(iss, OMAP4_ISS_MEM_BTE, BTE_CTRL,
1403 BTE_CTRL_BW_LIMITER_MASK,
1404 18 << BTE_CTRL_BW_LIMITER_SHIFT);
1405
1406
1407 ret = omap4iss_subclk_enable(iss, OMAP4_ISS_SUBCLK_ISP);
1408 if (ret < 0)
1409 goto error_iss;
1410
1411 ret = iss_isp_reset(iss);
1412 if (ret < 0)
1413 goto error_iss;
1414
1415 dev_info(iss->dev, "ISP Revision %08x found\n",
1416 iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_REVISION));
1417
1418
1419 iss->irq_num = platform_get_irq(pdev, 0);
1420 if (iss->irq_num <= 0) {
1421 dev_err(iss->dev, "No IRQ resource\n");
1422 ret = -ENODEV;
1423 goto error_iss;
1424 }
1425
1426 if (devm_request_irq(iss->dev, iss->irq_num, iss_isr, IRQF_SHARED,
1427 "OMAP4 ISS", iss)) {
1428 dev_err(iss->dev, "Unable to request IRQ\n");
1429 ret = -EINVAL;
1430 goto error_iss;
1431 }
1432
1433
1434 ret = iss_initialize_modules(iss);
1435 if (ret < 0)
1436 goto error_iss;
1437
1438 ret = iss_register_entities(iss);
1439 if (ret < 0)
1440 goto error_modules;
1441
1442 omap4iss_put(iss);
1443
1444 return 0;
1445
1446error_modules:
1447 iss_cleanup_modules(iss);
1448error_iss:
1449 omap4iss_put(iss);
1450error:
1451 platform_set_drvdata(pdev, NULL);
1452
1453 mutex_destroy(&iss->iss_mutex);
1454
1455 return ret;
1456}
1457
1458static int iss_remove(struct platform_device *pdev)
1459{
1460 struct iss_device *iss = platform_get_drvdata(pdev);
1461
1462 iss_unregister_entities(iss);
1463 iss_cleanup_modules(iss);
1464
1465 return 0;
1466}
1467
1468static struct platform_device_id omap4iss_id_table[] = {
1469 { "omap4iss", 0 },
1470 { },
1471};
1472MODULE_DEVICE_TABLE(platform, omap4iss_id_table);
1473
1474static struct platform_driver iss_driver = {
1475 .probe = iss_probe,
1476 .remove = iss_remove,
1477 .id_table = omap4iss_id_table,
1478 .driver = {
1479 .owner = THIS_MODULE,
1480 .name = "omap4iss",
1481 },
1482};
1483
1484module_platform_driver(iss_driver);
1485
1486MODULE_DESCRIPTION("TI OMAP4 ISS driver");
1487MODULE_AUTHOR("Sergio Aguirre <sergio.a.aguirre@gmail.com>");
1488MODULE_LICENSE("GPL");
1489MODULE_VERSION(ISS_VIDEO_DRIVER_VERSION);
1490