diff options
Diffstat (limited to 'drivers/media/platform')
55 files changed, 3689 insertions, 1909 deletions
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 8108c698b548..6d86646d9743 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig | |||
@@ -96,6 +96,7 @@ config VIDEO_OMAP3 | |||
96 | depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3 | 96 | depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3 |
97 | select ARM_DMA_USE_IOMMU | 97 | select ARM_DMA_USE_IOMMU |
98 | select OMAP_IOMMU | 98 | select OMAP_IOMMU |
99 | select VIDEOBUF2_DMA_CONTIG | ||
99 | ---help--- | 100 | ---help--- |
100 | Driver for an OMAP 3 camera controller. | 101 | Driver for an OMAP 3 camera controller. |
101 | 102 | ||
@@ -142,6 +143,7 @@ config VIDEO_CODA | |||
142 | select SRAM | 143 | select SRAM |
143 | select VIDEOBUF2_DMA_CONTIG | 144 | select VIDEOBUF2_DMA_CONTIG |
144 | select V4L2_MEM2MEM_DEV | 145 | select V4L2_MEM2MEM_DEV |
146 | select GENERIC_ALLOCATOR | ||
145 | ---help--- | 147 | ---help--- |
146 | Coda is a range of video codec IPs that supports | 148 | Coda is a range of video codec IPs that supports |
147 | H.264, MPEG-4, and other video formats. | 149 | H.264, MPEG-4, and other video formats. |
@@ -165,12 +167,13 @@ config VIDEO_SAMSUNG_S5P_G2D | |||
165 | 2d graphics accelerator. | 167 | 2d graphics accelerator. |
166 | 168 | ||
167 | config VIDEO_SAMSUNG_S5P_JPEG | 169 | config VIDEO_SAMSUNG_S5P_JPEG |
168 | tristate "Samsung S5P/Exynos4 JPEG codec driver" | 170 | tristate "Samsung S5P/Exynos3250/Exynos4 JPEG codec driver" |
169 | depends on VIDEO_DEV && VIDEO_V4L2 && (PLAT_S5P || ARCH_EXYNOS) | 171 | depends on VIDEO_DEV && VIDEO_V4L2 && (PLAT_S5P || ARCH_EXYNOS) |
170 | select VIDEOBUF2_DMA_CONTIG | 172 | select VIDEOBUF2_DMA_CONTIG |
171 | select V4L2_MEM2MEM_DEV | 173 | select V4L2_MEM2MEM_DEV |
172 | ---help--- | 174 | ---help--- |
173 | This is a v4l2 driver for Samsung S5P and EXYNOS4 JPEG codec | 175 | This is a v4l2 driver for Samsung S5P, EXYNOS3250 |
176 | and EXYNOS4 JPEG codec | ||
174 | 177 | ||
175 | config VIDEO_SAMSUNG_S5P_MFC | 178 | config VIDEO_SAMSUNG_S5P_MFC |
176 | tristate "Samsung S5P MFC Video Codec" | 179 | tristate "Samsung S5P MFC Video Codec" |
diff --git a/drivers/media/platform/arv.c b/drivers/media/platform/arv.c index e9410e41ae0c..03c5098499c4 100644 --- a/drivers/media/platform/arv.c +++ b/drivers/media/platform/arv.c | |||
@@ -773,7 +773,6 @@ static int __init ar_init(void) | |||
773 | ar->vdev.fops = &ar_fops; | 773 | ar->vdev.fops = &ar_fops; |
774 | ar->vdev.ioctl_ops = &ar_ioctl_ops; | 774 | ar->vdev.ioctl_ops = &ar_ioctl_ops; |
775 | ar->vdev.release = video_device_release_empty; | 775 | ar->vdev.release = video_device_release_empty; |
776 | set_bit(V4L2_FL_USE_FH_PRIO, &ar->vdev.flags); | ||
777 | video_set_drvdata(&ar->vdev, ar); | 776 | video_set_drvdata(&ar->vdev, ar); |
778 | 777 | ||
779 | if (vga) { | 778 | if (vga) { |
diff --git a/drivers/media/platform/blackfin/bfin_capture.c b/drivers/media/platform/blackfin/bfin_capture.c index 16e4b1c525c4..9b5daa65841c 100644 --- a/drivers/media/platform/blackfin/bfin_capture.c +++ b/drivers/media/platform/blackfin/bfin_capture.c | |||
@@ -446,7 +446,7 @@ static void bcap_stop_streaming(struct vb2_queue *vq) | |||
446 | while (!list_empty(&bcap_dev->dma_queue)) { | 446 | while (!list_empty(&bcap_dev->dma_queue)) { |
447 | bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next, | 447 | bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next, |
448 | struct bcap_buffer, list); | 448 | struct bcap_buffer, list); |
449 | list_del(&bcap_dev->cur_frm->list); | 449 | list_del_init(&bcap_dev->cur_frm->list); |
450 | vb2_buffer_done(&bcap_dev->cur_frm->vb, VB2_BUF_STATE_ERROR); | 450 | vb2_buffer_done(&bcap_dev->cur_frm->vb, VB2_BUF_STATE_ERROR); |
451 | } | 451 | } |
452 | } | 452 | } |
@@ -533,7 +533,7 @@ static irqreturn_t bcap_isr(int irq, void *dev_id) | |||
533 | } | 533 | } |
534 | bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next, | 534 | bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next, |
535 | struct bcap_buffer, list); | 535 | struct bcap_buffer, list); |
536 | list_del(&bcap_dev->cur_frm->list); | 536 | list_del_init(&bcap_dev->cur_frm->list); |
537 | } else { | 537 | } else { |
538 | /* clear error flag, we will get a new frame */ | 538 | /* clear error flag, we will get a new frame */ |
539 | if (ppi->err) | 539 | if (ppi->err) |
@@ -583,7 +583,7 @@ static int bcap_streamon(struct file *file, void *priv, | |||
583 | bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next, | 583 | bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next, |
584 | struct bcap_buffer, list); | 584 | struct bcap_buffer, list); |
585 | /* remove buffer from the dma queue */ | 585 | /* remove buffer from the dma queue */ |
586 | list_del(&bcap_dev->cur_frm->list); | 586 | list_del_init(&bcap_dev->cur_frm->list); |
587 | addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->cur_frm->vb, 0); | 587 | addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->cur_frm->vb, 0); |
588 | /* update DMA address */ | 588 | /* update DMA address */ |
589 | ppi->ops->update_addr(ppi, (unsigned long)addr); | 589 | ppi->ops->update_addr(ppi, (unsigned long)addr); |
@@ -939,7 +939,7 @@ static int bcap_probe(struct platform_device *pdev) | |||
939 | 939 | ||
940 | bcap_dev->cfg = config; | 940 | bcap_dev->cfg = config; |
941 | 941 | ||
942 | bcap_dev->ppi = ppi_create_instance(config->ppi_info); | 942 | bcap_dev->ppi = ppi_create_instance(pdev, config->ppi_info); |
943 | if (!bcap_dev->ppi) { | 943 | if (!bcap_dev->ppi) { |
944 | v4l2_err(pdev->dev.driver, "Unable to create ppi\n"); | 944 | v4l2_err(pdev->dev.driver, "Unable to create ppi\n"); |
945 | ret = -ENODEV; | 945 | ret = -ENODEV; |
@@ -966,7 +966,6 @@ static int bcap_probe(struct platform_device *pdev) | |||
966 | vfd->ioctl_ops = &bcap_ioctl_ops; | 966 | vfd->ioctl_ops = &bcap_ioctl_ops; |
967 | vfd->tvnorms = 0; | 967 | vfd->tvnorms = 0; |
968 | vfd->v4l2_dev = &bcap_dev->v4l2_dev; | 968 | vfd->v4l2_dev = &bcap_dev->v4l2_dev; |
969 | set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags); | ||
970 | strncpy(vfd->name, CAPTURE_DRV_NAME, sizeof(vfd->name)); | 969 | strncpy(vfd->name, CAPTURE_DRV_NAME, sizeof(vfd->name)); |
971 | bcap_dev->video_dev = vfd; | 970 | bcap_dev->video_dev = vfd; |
972 | 971 | ||
diff --git a/drivers/media/platform/blackfin/ppi.c b/drivers/media/platform/blackfin/ppi.c index 15e9c2bac2b1..cff63e511e6d 100644 --- a/drivers/media/platform/blackfin/ppi.c +++ b/drivers/media/platform/blackfin/ppi.c | |||
@@ -19,6 +19,7 @@ | |||
19 | 19 | ||
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/platform_device.h> | ||
22 | 23 | ||
23 | #include <asm/bfin_ppi.h> | 24 | #include <asm/bfin_ppi.h> |
24 | #include <asm/blackfin.h> | 25 | #include <asm/blackfin.h> |
@@ -205,6 +206,20 @@ static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params) | |||
205 | int dma_config, bytes_per_line; | 206 | int dma_config, bytes_per_line; |
206 | int hcount, hdelay, samples_per_line; | 207 | int hcount, hdelay, samples_per_line; |
207 | 208 | ||
209 | #ifdef CONFIG_PINCTRL | ||
210 | static const char * const pin_state[] = {"8bit", "16bit", "24bit"}; | ||
211 | struct pinctrl *pctrl; | ||
212 | struct pinctrl_state *pstate; | ||
213 | |||
214 | if (params->dlen > 24 || params->dlen <= 0) | ||
215 | return -EINVAL; | ||
216 | pctrl = devm_pinctrl_get(ppi->dev); | ||
217 | pstate = pinctrl_lookup_state(pctrl, | ||
218 | pin_state[(params->dlen + 7) / 8 - 1]); | ||
219 | if (pinctrl_select_state(pctrl, pstate)) | ||
220 | return -EINVAL; | ||
221 | #endif | ||
222 | |||
208 | bytes_per_line = params->width * params->bpp / 8; | 223 | bytes_per_line = params->width * params->bpp / 8; |
209 | /* convert parameters unit from pixels to samples */ | 224 | /* convert parameters unit from pixels to samples */ |
210 | hcount = params->width * params->bpp / params->dlen; | 225 | hcount = params->width * params->bpp / params->dlen; |
@@ -307,26 +322,30 @@ static void ppi_update_addr(struct ppi_if *ppi, unsigned long addr) | |||
307 | set_dma_start_addr(ppi->info->dma_ch, addr); | 322 | set_dma_start_addr(ppi->info->dma_ch, addr); |
308 | } | 323 | } |
309 | 324 | ||
310 | struct ppi_if *ppi_create_instance(const struct ppi_info *info) | 325 | struct ppi_if *ppi_create_instance(struct platform_device *pdev, |
326 | const struct ppi_info *info) | ||
311 | { | 327 | { |
312 | struct ppi_if *ppi; | 328 | struct ppi_if *ppi; |
313 | 329 | ||
314 | if (!info || !info->pin_req) | 330 | if (!info || !info->pin_req) |
315 | return NULL; | 331 | return NULL; |
316 | 332 | ||
333 | #ifndef CONFIG_PINCTRL | ||
317 | if (peripheral_request_list(info->pin_req, KBUILD_MODNAME)) { | 334 | if (peripheral_request_list(info->pin_req, KBUILD_MODNAME)) { |
318 | pr_err("request peripheral failed\n"); | 335 | dev_err(&pdev->dev, "request peripheral failed\n"); |
319 | return NULL; | 336 | return NULL; |
320 | } | 337 | } |
338 | #endif | ||
321 | 339 | ||
322 | ppi = kzalloc(sizeof(*ppi), GFP_KERNEL); | 340 | ppi = kzalloc(sizeof(*ppi), GFP_KERNEL); |
323 | if (!ppi) { | 341 | if (!ppi) { |
324 | peripheral_free_list(info->pin_req); | 342 | peripheral_free_list(info->pin_req); |
325 | pr_err("unable to allocate memory for ppi handle\n"); | 343 | dev_err(&pdev->dev, "unable to allocate memory for ppi handle\n"); |
326 | return NULL; | 344 | return NULL; |
327 | } | 345 | } |
328 | ppi->ops = &ppi_ops; | 346 | ppi->ops = &ppi_ops; |
329 | ppi->info = info; | 347 | ppi->info = info; |
348 | ppi->dev = &pdev->dev; | ||
330 | 349 | ||
331 | pr_info("ppi probe success\n"); | 350 | pr_info("ppi probe success\n"); |
332 | return ppi; | 351 | return ppi; |
diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index b1783791d426..3a6d1d2b429e 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c | |||
@@ -12,6 +12,7 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/clk.h> | 14 | #include <linux/clk.h> |
15 | #include <linux/debugfs.h> | ||
15 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
16 | #include <linux/firmware.h> | 17 | #include <linux/firmware.h> |
17 | #include <linux/genalloc.h> | 18 | #include <linux/genalloc.h> |
@@ -22,10 +23,12 @@ | |||
22 | #include <linux/module.h> | 23 | #include <linux/module.h> |
23 | #include <linux/of_device.h> | 24 | #include <linux/of_device.h> |
24 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
26 | #include <linux/pm_runtime.h> | ||
25 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
26 | #include <linux/videodev2.h> | 28 | #include <linux/videodev2.h> |
27 | #include <linux/of.h> | 29 | #include <linux/of.h> |
28 | #include <linux/platform_data/coda.h> | 30 | #include <linux/platform_data/coda.h> |
31 | #include <linux/reset.h> | ||
29 | 32 | ||
30 | #include <media/v4l2-ctrls.h> | 33 | #include <media/v4l2-ctrls.h> |
31 | #include <media/v4l2-device.h> | 34 | #include <media/v4l2-device.h> |
@@ -41,22 +44,18 @@ | |||
41 | 44 | ||
42 | #define CODADX6_MAX_INSTANCES 4 | 45 | #define CODADX6_MAX_INSTANCES 4 |
43 | 46 | ||
44 | #define CODA_FMO_BUF_SIZE 32 | ||
45 | #define CODADX6_WORK_BUF_SIZE (288 * 1024 + CODA_FMO_BUF_SIZE * 8 * 1024) | ||
46 | #define CODA7_WORK_BUF_SIZE (128 * 1024) | ||
47 | #define CODA7_TEMP_BUF_SIZE (304 * 1024) | ||
48 | #define CODA_PARA_BUF_SIZE (10 * 1024) | 47 | #define CODA_PARA_BUF_SIZE (10 * 1024) |
49 | #define CODA_ISRAM_SIZE (2048 * 2) | 48 | #define CODA_ISRAM_SIZE (2048 * 2) |
50 | #define CODADX6_IRAM_SIZE 0xb000 | ||
51 | #define CODA7_IRAM_SIZE 0x14000 | ||
52 | 49 | ||
53 | #define CODA7_PS_BUF_SIZE 0x28000 | 50 | #define CODA7_PS_BUF_SIZE 0x28000 |
51 | #define CODA9_PS_SAVE_SIZE (512 * 1024) | ||
54 | 52 | ||
55 | #define CODA_MAX_FRAMEBUFFERS 8 | 53 | #define CODA_MAX_FRAMEBUFFERS 8 |
56 | 54 | ||
57 | #define CODA_MAX_FRAME_SIZE 0x100000 | 55 | #define CODA_MAX_FRAME_SIZE 0x100000 |
58 | #define FMO_SLICE_SAVE_BUF_SIZE (32) | 56 | #define FMO_SLICE_SAVE_BUF_SIZE (32) |
59 | #define CODA_DEFAULT_GAMMA 4096 | 57 | #define CODA_DEFAULT_GAMMA 4096 |
58 | #define CODA9_DEFAULT_GAMMA 24576 /* 0.75 * 32768 */ | ||
60 | 59 | ||
61 | #define MIN_W 176 | 60 | #define MIN_W 176 |
62 | #define MIN_H 144 | 61 | #define MIN_H 144 |
@@ -84,6 +83,7 @@ enum coda_inst_type { | |||
84 | enum coda_product { | 83 | enum coda_product { |
85 | CODA_DX6 = 0xf001, | 84 | CODA_DX6 = 0xf001, |
86 | CODA_7541 = 0xf012, | 85 | CODA_7541 = 0xf012, |
86 | CODA_960 = 0xf020, | ||
87 | }; | 87 | }; |
88 | 88 | ||
89 | struct coda_fmt { | 89 | struct coda_fmt { |
@@ -105,20 +105,26 @@ struct coda_devtype { | |||
105 | struct coda_codec *codecs; | 105 | struct coda_codec *codecs; |
106 | unsigned int num_codecs; | 106 | unsigned int num_codecs; |
107 | size_t workbuf_size; | 107 | size_t workbuf_size; |
108 | size_t tempbuf_size; | ||
109 | size_t iram_size; | ||
108 | }; | 110 | }; |
109 | 111 | ||
110 | /* Per-queue, driver-specific private data */ | 112 | /* Per-queue, driver-specific private data */ |
111 | struct coda_q_data { | 113 | struct coda_q_data { |
112 | unsigned int width; | 114 | unsigned int width; |
113 | unsigned int height; | 115 | unsigned int height; |
116 | unsigned int bytesperline; | ||
114 | unsigned int sizeimage; | 117 | unsigned int sizeimage; |
115 | unsigned int fourcc; | 118 | unsigned int fourcc; |
119 | struct v4l2_rect rect; | ||
116 | }; | 120 | }; |
117 | 121 | ||
118 | struct coda_aux_buf { | 122 | struct coda_aux_buf { |
119 | void *vaddr; | 123 | void *vaddr; |
120 | dma_addr_t paddr; | 124 | dma_addr_t paddr; |
121 | u32 size; | 125 | u32 size; |
126 | struct debugfs_blob_wrapper blob; | ||
127 | struct dentry *dentry; | ||
122 | }; | 128 | }; |
123 | 129 | ||
124 | struct coda_dev { | 130 | struct coda_dev { |
@@ -130,32 +136,38 @@ struct coda_dev { | |||
130 | void __iomem *regs_base; | 136 | void __iomem *regs_base; |
131 | struct clk *clk_per; | 137 | struct clk *clk_per; |
132 | struct clk *clk_ahb; | 138 | struct clk *clk_ahb; |
139 | struct reset_control *rstc; | ||
133 | 140 | ||
134 | struct coda_aux_buf codebuf; | 141 | struct coda_aux_buf codebuf; |
135 | struct coda_aux_buf tempbuf; | 142 | struct coda_aux_buf tempbuf; |
136 | struct coda_aux_buf workbuf; | 143 | struct coda_aux_buf workbuf; |
137 | struct gen_pool *iram_pool; | 144 | struct gen_pool *iram_pool; |
138 | long unsigned int iram_vaddr; | 145 | struct coda_aux_buf iram; |
139 | long unsigned int iram_paddr; | ||
140 | unsigned long iram_size; | ||
141 | 146 | ||
142 | spinlock_t irqlock; | 147 | spinlock_t irqlock; |
143 | struct mutex dev_mutex; | 148 | struct mutex dev_mutex; |
144 | struct mutex coda_mutex; | 149 | struct mutex coda_mutex; |
150 | struct workqueue_struct *workqueue; | ||
145 | struct v4l2_m2m_dev *m2m_dev; | 151 | struct v4l2_m2m_dev *m2m_dev; |
146 | struct vb2_alloc_ctx *alloc_ctx; | 152 | struct vb2_alloc_ctx *alloc_ctx; |
147 | struct list_head instances; | 153 | struct list_head instances; |
148 | unsigned long instance_mask; | 154 | unsigned long instance_mask; |
149 | struct delayed_work timeout; | 155 | struct dentry *debugfs_root; |
150 | }; | 156 | }; |
151 | 157 | ||
152 | struct coda_params { | 158 | struct coda_params { |
153 | u8 rot_mode; | 159 | u8 rot_mode; |
154 | u8 h264_intra_qp; | 160 | u8 h264_intra_qp; |
155 | u8 h264_inter_qp; | 161 | u8 h264_inter_qp; |
162 | u8 h264_min_qp; | ||
163 | u8 h264_max_qp; | ||
164 | u8 h264_deblk_enabled; | ||
165 | u8 h264_deblk_alpha; | ||
166 | u8 h264_deblk_beta; | ||
156 | u8 mpeg4_intra_qp; | 167 | u8 mpeg4_intra_qp; |
157 | u8 mpeg4_inter_qp; | 168 | u8 mpeg4_inter_qp; |
158 | u8 gop_size; | 169 | u8 gop_size; |
170 | int intra_refresh; | ||
159 | int codec_mode; | 171 | int codec_mode; |
160 | int codec_mode_aux; | 172 | int codec_mode_aux; |
161 | enum v4l2_mpeg_video_multi_slice_mode slice_mode; | 173 | enum v4l2_mpeg_video_multi_slice_mode slice_mode; |
@@ -175,13 +187,34 @@ struct coda_iram_info { | |||
175 | phys_addr_t buf_btp_use; | 187 | phys_addr_t buf_btp_use; |
176 | phys_addr_t search_ram_paddr; | 188 | phys_addr_t search_ram_paddr; |
177 | int search_ram_size; | 189 | int search_ram_size; |
190 | int remaining; | ||
191 | phys_addr_t next_paddr; | ||
192 | }; | ||
193 | |||
194 | struct gdi_tiled_map { | ||
195 | int xy2ca_map[16]; | ||
196 | int xy2ba_map[16]; | ||
197 | int xy2ra_map[16]; | ||
198 | int rbc2axi_map[32]; | ||
199 | int xy2rbc_config; | ||
200 | int map_type; | ||
201 | #define GDI_LINEAR_FRAME_MAP 0 | ||
202 | }; | ||
203 | |||
204 | struct coda_timestamp { | ||
205 | struct list_head list; | ||
206 | u32 sequence; | ||
207 | struct v4l2_timecode timecode; | ||
208 | struct timeval timestamp; | ||
178 | }; | 209 | }; |
179 | 210 | ||
180 | struct coda_ctx { | 211 | struct coda_ctx { |
181 | struct coda_dev *dev; | 212 | struct coda_dev *dev; |
182 | struct mutex buffer_mutex; | 213 | struct mutex buffer_mutex; |
183 | struct list_head list; | 214 | struct list_head list; |
184 | struct work_struct skip_run; | 215 | struct work_struct pic_run_work; |
216 | struct work_struct seq_end_work; | ||
217 | struct completion completion; | ||
185 | int aborting; | 218 | int aborting; |
186 | int initialized; | 219 | int initialized; |
187 | int streamon_out; | 220 | int streamon_out; |
@@ -189,12 +222,12 @@ struct coda_ctx { | |||
189 | u32 isequence; | 222 | u32 isequence; |
190 | u32 qsequence; | 223 | u32 qsequence; |
191 | u32 osequence; | 224 | u32 osequence; |
225 | u32 sequence_offset; | ||
192 | struct coda_q_data q_data[2]; | 226 | struct coda_q_data q_data[2]; |
193 | enum coda_inst_type inst_type; | 227 | enum coda_inst_type inst_type; |
194 | struct coda_codec *codec; | 228 | struct coda_codec *codec; |
195 | enum v4l2_colorspace colorspace; | 229 | enum v4l2_colorspace colorspace; |
196 | struct coda_params params; | 230 | struct coda_params params; |
197 | struct v4l2_m2m_ctx *m2m_ctx; | ||
198 | struct v4l2_ctrl_handler ctrls; | 231 | struct v4l2_ctrl_handler ctrls; |
199 | struct v4l2_fh fh; | 232 | struct v4l2_fh fh; |
200 | int gopcounter; | 233 | int gopcounter; |
@@ -204,19 +237,26 @@ struct coda_ctx { | |||
204 | struct kfifo bitstream_fifo; | 237 | struct kfifo bitstream_fifo; |
205 | struct mutex bitstream_mutex; | 238 | struct mutex bitstream_mutex; |
206 | struct coda_aux_buf bitstream; | 239 | struct coda_aux_buf bitstream; |
207 | bool prescan_failed; | 240 | bool hold; |
208 | struct coda_aux_buf parabuf; | 241 | struct coda_aux_buf parabuf; |
209 | struct coda_aux_buf psbuf; | 242 | struct coda_aux_buf psbuf; |
210 | struct coda_aux_buf slicebuf; | 243 | struct coda_aux_buf slicebuf; |
211 | struct coda_aux_buf internal_frames[CODA_MAX_FRAMEBUFFERS]; | 244 | struct coda_aux_buf internal_frames[CODA_MAX_FRAMEBUFFERS]; |
245 | u32 frame_types[CODA_MAX_FRAMEBUFFERS]; | ||
246 | struct coda_timestamp frame_timestamps[CODA_MAX_FRAMEBUFFERS]; | ||
247 | u32 frame_errors[CODA_MAX_FRAMEBUFFERS]; | ||
248 | struct list_head timestamp_list; | ||
212 | struct coda_aux_buf workbuf; | 249 | struct coda_aux_buf workbuf; |
213 | int num_internal_frames; | 250 | int num_internal_frames; |
214 | int idx; | 251 | int idx; |
215 | int reg_idx; | 252 | int reg_idx; |
216 | struct coda_iram_info iram_info; | 253 | struct coda_iram_info iram_info; |
254 | struct gdi_tiled_map tiled_map; | ||
217 | u32 bit_stream_param; | 255 | u32 bit_stream_param; |
218 | u32 frm_dis_flg; | 256 | u32 frm_dis_flg; |
257 | u32 frame_mem_ctrl; | ||
219 | int display_idx; | 258 | int display_idx; |
259 | struct dentry *debugfs_entry; | ||
220 | }; | 260 | }; |
221 | 261 | ||
222 | static const u8 coda_filler_nal[14] = { 0x00, 0x00, 0x00, 0x01, 0x0c, 0xff, | 262 | static const u8 coda_filler_nal[14] = { 0x00, 0x00, 0x00, 0x01, 0x0c, 0xff, |
@@ -264,15 +304,23 @@ static void coda_command_async(struct coda_ctx *ctx, int cmd) | |||
264 | { | 304 | { |
265 | struct coda_dev *dev = ctx->dev; | 305 | struct coda_dev *dev = ctx->dev; |
266 | 306 | ||
267 | if (dev->devtype->product == CODA_7541) { | 307 | if (dev->devtype->product == CODA_960 || |
308 | dev->devtype->product == CODA_7541) { | ||
268 | /* Restore context related registers to CODA */ | 309 | /* Restore context related registers to CODA */ |
269 | coda_write(dev, ctx->bit_stream_param, | 310 | coda_write(dev, ctx->bit_stream_param, |
270 | CODA_REG_BIT_BIT_STREAM_PARAM); | 311 | CODA_REG_BIT_BIT_STREAM_PARAM); |
271 | coda_write(dev, ctx->frm_dis_flg, | 312 | coda_write(dev, ctx->frm_dis_flg, |
272 | CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx)); | 313 | CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx)); |
314 | coda_write(dev, ctx->frame_mem_ctrl, | ||
315 | CODA_REG_BIT_FRAME_MEM_CTRL); | ||
273 | coda_write(dev, ctx->workbuf.paddr, CODA_REG_BIT_WORK_BUF_ADDR); | 316 | coda_write(dev, ctx->workbuf.paddr, CODA_REG_BIT_WORK_BUF_ADDR); |
274 | } | 317 | } |
275 | 318 | ||
319 | if (dev->devtype->product == CODA_960) { | ||
320 | coda_write(dev, 1, CODA9_GDI_WPROT_ERR_CLR); | ||
321 | coda_write(dev, 0, CODA9_GDI_WPROT_RGN_EN); | ||
322 | } | ||
323 | |||
276 | coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY); | 324 | coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY); |
277 | 325 | ||
278 | coda_write(dev, ctx->idx, CODA_REG_BIT_RUN_INDEX); | 326 | coda_write(dev, ctx->idx, CODA_REG_BIT_RUN_INDEX); |
@@ -290,6 +338,39 @@ static int coda_command_sync(struct coda_ctx *ctx, int cmd) | |||
290 | return coda_wait_timeout(dev); | 338 | return coda_wait_timeout(dev); |
291 | } | 339 | } |
292 | 340 | ||
341 | static int coda_hw_reset(struct coda_ctx *ctx) | ||
342 | { | ||
343 | struct coda_dev *dev = ctx->dev; | ||
344 | unsigned long timeout; | ||
345 | unsigned int idx; | ||
346 | int ret; | ||
347 | |||
348 | if (!dev->rstc) | ||
349 | return -ENOENT; | ||
350 | |||
351 | idx = coda_read(dev, CODA_REG_BIT_RUN_INDEX); | ||
352 | |||
353 | timeout = jiffies + msecs_to_jiffies(100); | ||
354 | coda_write(dev, 0x11, CODA9_GDI_BUS_CTRL); | ||
355 | while (coda_read(dev, CODA9_GDI_BUS_STATUS) != 0x77) { | ||
356 | if (time_after(jiffies, timeout)) | ||
357 | return -ETIME; | ||
358 | cpu_relax(); | ||
359 | } | ||
360 | |||
361 | ret = reset_control_reset(dev->rstc); | ||
362 | if (ret < 0) | ||
363 | return ret; | ||
364 | |||
365 | coda_write(dev, 0x00, CODA9_GDI_BUS_CTRL); | ||
366 | coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY); | ||
367 | coda_write(dev, CODA_REG_RUN_ENABLE, CODA_REG_BIT_CODE_RUN); | ||
368 | ret = coda_wait_timeout(dev); | ||
369 | coda_write(dev, idx, CODA_REG_BIT_RUN_INDEX); | ||
370 | |||
371 | return ret; | ||
372 | } | ||
373 | |||
293 | static struct coda_q_data *get_q_data(struct coda_ctx *ctx, | 374 | static struct coda_q_data *get_q_data(struct coda_ctx *ctx, |
294 | enum v4l2_buf_type type) | 375 | enum v4l2_buf_type type) |
295 | { | 376 | { |
@@ -299,9 +380,8 @@ static struct coda_q_data *get_q_data(struct coda_ctx *ctx, | |||
299 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 380 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
300 | return &(ctx->q_data[V4L2_M2M_DST]); | 381 | return &(ctx->q_data[V4L2_M2M_DST]); |
301 | default: | 382 | default: |
302 | BUG(); | 383 | return NULL; |
303 | } | 384 | } |
304 | return NULL; | ||
305 | } | 385 | } |
306 | 386 | ||
307 | /* | 387 | /* |
@@ -348,6 +428,13 @@ static struct coda_codec coda7_codecs[] = { | |||
348 | CODA_CODEC(CODA7_MODE_DECODE_MP4, V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_YUV420, 1920, 1080), | 428 | CODA_CODEC(CODA7_MODE_DECODE_MP4, V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_YUV420, 1920, 1080), |
349 | }; | 429 | }; |
350 | 430 | ||
431 | static struct coda_codec coda9_codecs[] = { | ||
432 | CODA_CODEC(CODA9_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264, 1920, 1080), | ||
433 | CODA_CODEC(CODA9_MODE_ENCODE_MP4, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4, 1920, 1080), | ||
434 | CODA_CODEC(CODA9_MODE_DECODE_H264, V4L2_PIX_FMT_H264, V4L2_PIX_FMT_YUV420, 1920, 1080), | ||
435 | CODA_CODEC(CODA9_MODE_DECODE_MP4, V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_YUV420, 1920, 1080), | ||
436 | }; | ||
437 | |||
351 | static bool coda_format_is_yuv(u32 fourcc) | 438 | static bool coda_format_is_yuv(u32 fourcc) |
352 | { | 439 | { |
353 | switch (fourcc) { | 440 | switch (fourcc) { |
@@ -426,6 +513,8 @@ static char *coda_product_name(int product) | |||
426 | return "CodaDx6"; | 513 | return "CodaDx6"; |
427 | case CODA_7541: | 514 | case CODA_7541: |
428 | return "CODA7541"; | 515 | return "CODA7541"; |
516 | case CODA_960: | ||
517 | return "CODA960"; | ||
429 | default: | 518 | default: |
430 | snprintf(buf, sizeof(buf), "(0x%04x)", product); | 519 | snprintf(buf, sizeof(buf), "(0x%04x)", product); |
431 | return buf; | 520 | return buf; |
@@ -515,7 +604,7 @@ static int coda_enum_fmt_vid_cap(struct file *file, void *priv, | |||
515 | struct coda_q_data *q_data_src; | 604 | struct coda_q_data *q_data_src; |
516 | 605 | ||
517 | /* If the source format is already fixed, only list matching formats */ | 606 | /* If the source format is already fixed, only list matching formats */ |
518 | src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | 607 | src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); |
519 | if (vb2_is_streaming(src_vq)) { | 608 | if (vb2_is_streaming(src_vq)) { |
520 | q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | 609 | q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); |
521 | 610 | ||
@@ -535,24 +624,18 @@ static int coda_enum_fmt_vid_out(struct file *file, void *priv, | |||
535 | static int coda_g_fmt(struct file *file, void *priv, | 624 | static int coda_g_fmt(struct file *file, void *priv, |
536 | struct v4l2_format *f) | 625 | struct v4l2_format *f) |
537 | { | 626 | { |
538 | struct vb2_queue *vq; | ||
539 | struct coda_q_data *q_data; | 627 | struct coda_q_data *q_data; |
540 | struct coda_ctx *ctx = fh_to_ctx(priv); | 628 | struct coda_ctx *ctx = fh_to_ctx(priv); |
541 | 629 | ||
542 | vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); | ||
543 | if (!vq) | ||
544 | return -EINVAL; | ||
545 | |||
546 | q_data = get_q_data(ctx, f->type); | 630 | q_data = get_q_data(ctx, f->type); |
631 | if (!q_data) | ||
632 | return -EINVAL; | ||
547 | 633 | ||
548 | f->fmt.pix.field = V4L2_FIELD_NONE; | 634 | f->fmt.pix.field = V4L2_FIELD_NONE; |
549 | f->fmt.pix.pixelformat = q_data->fourcc; | 635 | f->fmt.pix.pixelformat = q_data->fourcc; |
550 | f->fmt.pix.width = q_data->width; | 636 | f->fmt.pix.width = q_data->width; |
551 | f->fmt.pix.height = q_data->height; | 637 | f->fmt.pix.height = q_data->height; |
552 | if (coda_format_is_yuv(f->fmt.pix.pixelformat)) | 638 | f->fmt.pix.bytesperline = q_data->bytesperline; |
553 | f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 2); | ||
554 | else /* encoded formats h.264/mpeg4 */ | ||
555 | f->fmt.pix.bytesperline = 0; | ||
556 | 639 | ||
557 | f->fmt.pix.sizeimage = q_data->sizeimage; | 640 | f->fmt.pix.sizeimage = q_data->sizeimage; |
558 | f->fmt.pix.colorspace = ctx->colorspace; | 641 | f->fmt.pix.colorspace = ctx->colorspace; |
@@ -592,14 +675,16 @@ static int coda_try_fmt(struct coda_ctx *ctx, struct coda_codec *codec, | |||
592 | break; | 675 | break; |
593 | default: | 676 | default: |
594 | q_data = get_q_data(ctx, f->type); | 677 | q_data = get_q_data(ctx, f->type); |
678 | if (!q_data) | ||
679 | return -EINVAL; | ||
595 | f->fmt.pix.pixelformat = q_data->fourcc; | 680 | f->fmt.pix.pixelformat = q_data->fourcc; |
596 | } | 681 | } |
597 | 682 | ||
598 | switch (f->fmt.pix.pixelformat) { | 683 | switch (f->fmt.pix.pixelformat) { |
599 | case V4L2_PIX_FMT_YUV420: | 684 | case V4L2_PIX_FMT_YUV420: |
600 | case V4L2_PIX_FMT_YVU420: | 685 | case V4L2_PIX_FMT_YVU420: |
601 | /* Frame stride must be multiple of 8 */ | 686 | /* Frame stride must be multiple of 8, but 16 for h.264 */ |
602 | f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 8); | 687 | f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16); |
603 | f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * | 688 | f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * |
604 | f->fmt.pix.height * 3 / 2; | 689 | f->fmt.pix.height * 3 / 2; |
605 | break; | 690 | break; |
@@ -613,8 +698,6 @@ static int coda_try_fmt(struct coda_ctx *ctx, struct coda_codec *codec, | |||
613 | BUG(); | 698 | BUG(); |
614 | } | 699 | } |
615 | 700 | ||
616 | f->fmt.pix.priv = 0; | ||
617 | |||
618 | return 0; | 701 | return 0; |
619 | } | 702 | } |
620 | 703 | ||
@@ -630,7 +713,7 @@ static int coda_try_fmt_vid_cap(struct file *file, void *priv, | |||
630 | * If the source format is already fixed, try to find a codec that | 713 | * If the source format is already fixed, try to find a codec that |
631 | * converts to the given destination format | 714 | * converts to the given destination format |
632 | */ | 715 | */ |
633 | src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | 716 | src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); |
634 | if (vb2_is_streaming(src_vq)) { | 717 | if (vb2_is_streaming(src_vq)) { |
635 | struct coda_q_data *q_data_src; | 718 | struct coda_q_data *q_data_src; |
636 | 719 | ||
@@ -653,9 +736,9 @@ static int coda_try_fmt_vid_cap(struct file *file, void *priv, | |||
653 | 736 | ||
654 | /* The h.264 decoder only returns complete 16x16 macroblocks */ | 737 | /* The h.264 decoder only returns complete 16x16 macroblocks */ |
655 | if (codec && codec->src_fourcc == V4L2_PIX_FMT_H264) { | 738 | if (codec && codec->src_fourcc == V4L2_PIX_FMT_H264) { |
656 | f->fmt.pix.width = round_up(f->fmt.pix.width, 16); | 739 | f->fmt.pix.width = f->fmt.pix.width; |
657 | f->fmt.pix.height = round_up(f->fmt.pix.height, 16); | 740 | f->fmt.pix.height = round_up(f->fmt.pix.height, 16); |
658 | f->fmt.pix.bytesperline = f->fmt.pix.width; | 741 | f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16); |
659 | f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * | 742 | f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * |
660 | f->fmt.pix.height * 3 / 2; | 743 | f->fmt.pix.height * 3 / 2; |
661 | } | 744 | } |
@@ -684,7 +767,7 @@ static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f) | |||
684 | struct coda_q_data *q_data; | 767 | struct coda_q_data *q_data; |
685 | struct vb2_queue *vq; | 768 | struct vb2_queue *vq; |
686 | 769 | ||
687 | vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); | 770 | vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); |
688 | if (!vq) | 771 | if (!vq) |
689 | return -EINVAL; | 772 | return -EINVAL; |
690 | 773 | ||
@@ -700,7 +783,12 @@ static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f) | |||
700 | q_data->fourcc = f->fmt.pix.pixelformat; | 783 | q_data->fourcc = f->fmt.pix.pixelformat; |
701 | q_data->width = f->fmt.pix.width; | 784 | q_data->width = f->fmt.pix.width; |
702 | q_data->height = f->fmt.pix.height; | 785 | q_data->height = f->fmt.pix.height; |
786 | q_data->bytesperline = f->fmt.pix.bytesperline; | ||
703 | q_data->sizeimage = f->fmt.pix.sizeimage; | 787 | q_data->sizeimage = f->fmt.pix.sizeimage; |
788 | q_data->rect.left = 0; | ||
789 | q_data->rect.top = 0; | ||
790 | q_data->rect.width = f->fmt.pix.width; | ||
791 | q_data->rect.height = f->fmt.pix.height; | ||
704 | 792 | ||
705 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, | 793 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, |
706 | "Setting format for type %d, wxh: %dx%d, fmt: %d\n", | 794 | "Setting format for type %d, wxh: %dx%d, fmt: %d\n", |
@@ -739,36 +827,12 @@ static int coda_s_fmt_vid_out(struct file *file, void *priv, | |||
739 | return ret; | 827 | return ret; |
740 | } | 828 | } |
741 | 829 | ||
742 | static int coda_reqbufs(struct file *file, void *priv, | ||
743 | struct v4l2_requestbuffers *reqbufs) | ||
744 | { | ||
745 | struct coda_ctx *ctx = fh_to_ctx(priv); | ||
746 | |||
747 | return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); | ||
748 | } | ||
749 | |||
750 | static int coda_querybuf(struct file *file, void *priv, | ||
751 | struct v4l2_buffer *buf) | ||
752 | { | ||
753 | struct coda_ctx *ctx = fh_to_ctx(priv); | ||
754 | |||
755 | return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); | ||
756 | } | ||
757 | |||
758 | static int coda_qbuf(struct file *file, void *priv, | 830 | static int coda_qbuf(struct file *file, void *priv, |
759 | struct v4l2_buffer *buf) | 831 | struct v4l2_buffer *buf) |
760 | { | 832 | { |
761 | struct coda_ctx *ctx = fh_to_ctx(priv); | 833 | struct coda_ctx *ctx = fh_to_ctx(priv); |
762 | 834 | ||
763 | return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); | 835 | return v4l2_m2m_qbuf(file, ctx->fh.m2m_ctx, buf); |
764 | } | ||
765 | |||
766 | static int coda_expbuf(struct file *file, void *priv, | ||
767 | struct v4l2_exportbuffer *eb) | ||
768 | { | ||
769 | struct coda_ctx *ctx = fh_to_ctx(priv); | ||
770 | |||
771 | return v4l2_m2m_expbuf(file, ctx->m2m_ctx, eb); | ||
772 | } | 836 | } |
773 | 837 | ||
774 | static bool coda_buf_is_end_of_stream(struct coda_ctx *ctx, | 838 | static bool coda_buf_is_end_of_stream(struct coda_ctx *ctx, |
@@ -776,7 +840,7 @@ static bool coda_buf_is_end_of_stream(struct coda_ctx *ctx, | |||
776 | { | 840 | { |
777 | struct vb2_queue *src_vq; | 841 | struct vb2_queue *src_vq; |
778 | 842 | ||
779 | src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | 843 | src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); |
780 | 844 | ||
781 | return ((ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG) && | 845 | return ((ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG) && |
782 | (buf->sequence == (ctx->qsequence - 1))); | 846 | (buf->sequence == (ctx->qsequence - 1))); |
@@ -788,7 +852,7 @@ static int coda_dqbuf(struct file *file, void *priv, | |||
788 | struct coda_ctx *ctx = fh_to_ctx(priv); | 852 | struct coda_ctx *ctx = fh_to_ctx(priv); |
789 | int ret; | 853 | int ret; |
790 | 854 | ||
791 | ret = v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); | 855 | ret = v4l2_m2m_dqbuf(file, ctx->fh.m2m_ctx, buf); |
792 | 856 | ||
793 | /* If this is the last capture buffer, emit an end-of-stream event */ | 857 | /* If this is the last capture buffer, emit an end-of-stream event */ |
794 | if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && | 858 | if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && |
@@ -803,38 +867,48 @@ static int coda_dqbuf(struct file *file, void *priv, | |||
803 | return ret; | 867 | return ret; |
804 | } | 868 | } |
805 | 869 | ||
806 | static int coda_create_bufs(struct file *file, void *priv, | 870 | static int coda_g_selection(struct file *file, void *fh, |
807 | struct v4l2_create_buffers *create) | 871 | struct v4l2_selection *s) |
808 | { | 872 | { |
809 | struct coda_ctx *ctx = fh_to_ctx(priv); | 873 | struct coda_ctx *ctx = fh_to_ctx(fh); |
810 | 874 | struct coda_q_data *q_data; | |
811 | return v4l2_m2m_create_bufs(file, ctx->m2m_ctx, create); | 875 | struct v4l2_rect r, *rsel; |
812 | } | ||
813 | |||
814 | static int coda_streamon(struct file *file, void *priv, | ||
815 | enum v4l2_buf_type type) | ||
816 | { | ||
817 | struct coda_ctx *ctx = fh_to_ctx(priv); | ||
818 | 876 | ||
819 | return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); | 877 | q_data = get_q_data(ctx, s->type); |
820 | } | 878 | if (!q_data) |
879 | return -EINVAL; | ||
821 | 880 | ||
822 | static int coda_streamoff(struct file *file, void *priv, | 881 | r.left = 0; |
823 | enum v4l2_buf_type type) | 882 | r.top = 0; |
824 | { | 883 | r.width = q_data->width; |
825 | struct coda_ctx *ctx = fh_to_ctx(priv); | 884 | r.height = q_data->height; |
826 | int ret; | 885 | rsel = &q_data->rect; |
886 | |||
887 | switch (s->target) { | ||
888 | case V4L2_SEL_TGT_CROP_DEFAULT: | ||
889 | case V4L2_SEL_TGT_CROP_BOUNDS: | ||
890 | rsel = &r; | ||
891 | /* fallthrough */ | ||
892 | case V4L2_SEL_TGT_CROP: | ||
893 | if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) | ||
894 | return -EINVAL; | ||
895 | break; | ||
896 | case V4L2_SEL_TGT_COMPOSE_BOUNDS: | ||
897 | case V4L2_SEL_TGT_COMPOSE_PADDED: | ||
898 | rsel = &r; | ||
899 | /* fallthrough */ | ||
900 | case V4L2_SEL_TGT_COMPOSE: | ||
901 | case V4L2_SEL_TGT_COMPOSE_DEFAULT: | ||
902 | if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
903 | return -EINVAL; | ||
904 | break; | ||
905 | default: | ||
906 | return -EINVAL; | ||
907 | } | ||
827 | 908 | ||
828 | /* | 909 | s->r = *rsel; |
829 | * This indirectly calls __vb2_queue_cancel, which dequeues all buffers. | ||
830 | * We therefore have to lock it against running hardware in this context, | ||
831 | * which still needs the buffers. | ||
832 | */ | ||
833 | mutex_lock(&ctx->buffer_mutex); | ||
834 | ret = v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); | ||
835 | mutex_unlock(&ctx->buffer_mutex); | ||
836 | 910 | ||
837 | return ret; | 911 | return 0; |
838 | } | 912 | } |
839 | 913 | ||
840 | static int coda_try_decoder_cmd(struct file *file, void *fh, | 914 | static int coda_try_decoder_cmd(struct file *file, void *fh, |
@@ -856,6 +930,7 @@ static int coda_decoder_cmd(struct file *file, void *fh, | |||
856 | struct v4l2_decoder_cmd *dc) | 930 | struct v4l2_decoder_cmd *dc) |
857 | { | 931 | { |
858 | struct coda_ctx *ctx = fh_to_ctx(fh); | 932 | struct coda_ctx *ctx = fh_to_ctx(fh); |
933 | struct coda_dev *dev = ctx->dev; | ||
859 | int ret; | 934 | int ret; |
860 | 935 | ||
861 | ret = coda_try_decoder_cmd(file, fh, dc); | 936 | ret = coda_try_decoder_cmd(file, fh, dc); |
@@ -869,6 +944,15 @@ static int coda_decoder_cmd(struct file *file, void *fh, | |||
869 | /* Set the strem-end flag on this context */ | 944 | /* Set the strem-end flag on this context */ |
870 | ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG; | 945 | ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG; |
871 | 946 | ||
947 | if ((dev->devtype->product == CODA_960) && | ||
948 | coda_isbusy(dev) && | ||
949 | (ctx->idx == coda_read(dev, CODA_REG_BIT_RUN_INDEX))) { | ||
950 | /* If this context is currently running, update the hardware flag */ | ||
951 | coda_write(dev, ctx->bit_stream_param, CODA_REG_BIT_BIT_STREAM_PARAM); | ||
952 | } | ||
953 | ctx->hold = false; | ||
954 | v4l2_m2m_try_schedule(ctx->fh.m2m_ctx); | ||
955 | |||
872 | return 0; | 956 | return 0; |
873 | } | 957 | } |
874 | 958 | ||
@@ -896,16 +980,18 @@ static const struct v4l2_ioctl_ops coda_ioctl_ops = { | |||
896 | .vidioc_try_fmt_vid_out = coda_try_fmt_vid_out, | 980 | .vidioc_try_fmt_vid_out = coda_try_fmt_vid_out, |
897 | .vidioc_s_fmt_vid_out = coda_s_fmt_vid_out, | 981 | .vidioc_s_fmt_vid_out = coda_s_fmt_vid_out, |
898 | 982 | ||
899 | .vidioc_reqbufs = coda_reqbufs, | 983 | .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, |
900 | .vidioc_querybuf = coda_querybuf, | 984 | .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, |
901 | 985 | ||
902 | .vidioc_qbuf = coda_qbuf, | 986 | .vidioc_qbuf = coda_qbuf, |
903 | .vidioc_expbuf = coda_expbuf, | 987 | .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, |
904 | .vidioc_dqbuf = coda_dqbuf, | 988 | .vidioc_dqbuf = coda_dqbuf, |
905 | .vidioc_create_bufs = coda_create_bufs, | 989 | .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, |
906 | 990 | ||
907 | .vidioc_streamon = coda_streamon, | 991 | .vidioc_streamon = v4l2_m2m_ioctl_streamon, |
908 | .vidioc_streamoff = coda_streamoff, | 992 | .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, |
993 | |||
994 | .vidioc_g_selection = coda_g_selection, | ||
909 | 995 | ||
910 | .vidioc_try_decoder_cmd = coda_try_decoder_cmd, | 996 | .vidioc_try_decoder_cmd = coda_try_decoder_cmd, |
911 | .vidioc_decoder_cmd = coda_decoder_cmd, | 997 | .vidioc_decoder_cmd = coda_decoder_cmd, |
@@ -916,13 +1002,6 @@ static const struct v4l2_ioctl_ops coda_ioctl_ops = { | |||
916 | 1002 | ||
917 | static int coda_start_decoding(struct coda_ctx *ctx); | 1003 | static int coda_start_decoding(struct coda_ctx *ctx); |
918 | 1004 | ||
919 | static void coda_skip_run(struct work_struct *work) | ||
920 | { | ||
921 | struct coda_ctx *ctx = container_of(work, struct coda_ctx, skip_run); | ||
922 | |||
923 | v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->m2m_ctx); | ||
924 | } | ||
925 | |||
926 | static inline int coda_get_bitstream_payload(struct coda_ctx *ctx) | 1005 | static inline int coda_get_bitstream_payload(struct coda_ctx *ctx) |
927 | { | 1006 | { |
928 | return kfifo_len(&ctx->bitstream_fifo); | 1007 | return kfifo_len(&ctx->bitstream_fifo); |
@@ -975,7 +1054,7 @@ static int coda_bitstream_queue(struct coda_ctx *ctx, struct vb2_buffer *src_buf | |||
975 | dma_sync_single_for_device(&ctx->dev->plat_dev->dev, ctx->bitstream.paddr, | 1054 | dma_sync_single_for_device(&ctx->dev->plat_dev->dev, ctx->bitstream.paddr, |
976 | ctx->bitstream.size, DMA_TO_DEVICE); | 1055 | ctx->bitstream.size, DMA_TO_DEVICE); |
977 | 1056 | ||
978 | ctx->qsequence++; | 1057 | src_buf->v4l2_buf.sequence = ctx->qsequence++; |
979 | 1058 | ||
980 | return 0; | 1059 | return 0; |
981 | } | 1060 | } |
@@ -1003,7 +1082,7 @@ static bool coda_bitstream_try_queue(struct coda_ctx *ctx, | |||
1003 | if (ctx == v4l2_m2m_get_curr_priv(ctx->dev->m2m_dev)) | 1082 | if (ctx == v4l2_m2m_get_curr_priv(ctx->dev->m2m_dev)) |
1004 | coda_kfifo_sync_to_device_write(ctx); | 1083 | coda_kfifo_sync_to_device_write(ctx); |
1005 | 1084 | ||
1006 | ctx->prescan_failed = false; | 1085 | ctx->hold = false; |
1007 | 1086 | ||
1008 | return true; | 1087 | return true; |
1009 | } | 1088 | } |
@@ -1011,12 +1090,26 @@ static bool coda_bitstream_try_queue(struct coda_ctx *ctx, | |||
1011 | static void coda_fill_bitstream(struct coda_ctx *ctx) | 1090 | static void coda_fill_bitstream(struct coda_ctx *ctx) |
1012 | { | 1091 | { |
1013 | struct vb2_buffer *src_buf; | 1092 | struct vb2_buffer *src_buf; |
1093 | struct coda_timestamp *ts; | ||
1014 | 1094 | ||
1015 | while (v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) > 0) { | 1095 | while (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) > 0) { |
1016 | src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); | 1096 | src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); |
1017 | 1097 | ||
1018 | if (coda_bitstream_try_queue(ctx, src_buf)) { | 1098 | if (coda_bitstream_try_queue(ctx, src_buf)) { |
1019 | src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); | 1099 | /* |
1100 | * Source buffer is queued in the bitstream ringbuffer; | ||
1101 | * queue the timestamp and mark source buffer as done | ||
1102 | */ | ||
1103 | src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); | ||
1104 | |||
1105 | ts = kmalloc(sizeof(*ts), GFP_KERNEL); | ||
1106 | if (ts) { | ||
1107 | ts->sequence = src_buf->v4l2_buf.sequence; | ||
1108 | ts->timecode = src_buf->v4l2_buf.timecode; | ||
1109 | ts->timestamp = src_buf->v4l2_buf.timestamp; | ||
1110 | list_add_tail(&ts->list, &ctx->timestamp_list); | ||
1111 | } | ||
1112 | |||
1020 | v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); | 1113 | v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); |
1021 | } else { | 1114 | } else { |
1022 | break; | 1115 | break; |
@@ -1024,6 +1117,27 @@ static void coda_fill_bitstream(struct coda_ctx *ctx) | |||
1024 | } | 1117 | } |
1025 | } | 1118 | } |
1026 | 1119 | ||
1120 | static void coda_set_gdi_regs(struct coda_ctx *ctx) | ||
1121 | { | ||
1122 | struct gdi_tiled_map *tiled_map = &ctx->tiled_map; | ||
1123 | struct coda_dev *dev = ctx->dev; | ||
1124 | int i; | ||
1125 | |||
1126 | for (i = 0; i < 16; i++) | ||
1127 | coda_write(dev, tiled_map->xy2ca_map[i], | ||
1128 | CODA9_GDI_XY2_CAS_0 + 4 * i); | ||
1129 | for (i = 0; i < 4; i++) | ||
1130 | coda_write(dev, tiled_map->xy2ba_map[i], | ||
1131 | CODA9_GDI_XY2_BA_0 + 4 * i); | ||
1132 | for (i = 0; i < 16; i++) | ||
1133 | coda_write(dev, tiled_map->xy2ra_map[i], | ||
1134 | CODA9_GDI_XY2_RAS_0 + 4 * i); | ||
1135 | coda_write(dev, tiled_map->xy2rbc_config, CODA9_GDI_XY2_RBC_CONFIG); | ||
1136 | for (i = 0; i < 32; i++) | ||
1137 | coda_write(dev, tiled_map->rbc2axi_map[i], | ||
1138 | CODA9_GDI_RBC2_AXI_0 + 4 * i); | ||
1139 | } | ||
1140 | |||
1027 | /* | 1141 | /* |
1028 | * Mem-to-mem operations. | 1142 | * Mem-to-mem operations. |
1029 | */ | 1143 | */ |
@@ -1035,7 +1149,7 @@ static int coda_prepare_decode(struct coda_ctx *ctx) | |||
1035 | u32 stridey, height; | 1149 | u32 stridey, height; |
1036 | u32 picture_y, picture_cb, picture_cr; | 1150 | u32 picture_y, picture_cb, picture_cr; |
1037 | 1151 | ||
1038 | dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); | 1152 | dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); |
1039 | q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); | 1153 | q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); |
1040 | 1154 | ||
1041 | if (ctx->params.rot_mode & CODA_ROT_90) { | 1155 | if (ctx->params.rot_mode & CODA_ROT_90) { |
@@ -1056,7 +1170,7 @@ static int coda_prepare_decode(struct coda_ctx *ctx) | |||
1056 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, | 1170 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, |
1057 | "bitstream payload: %d, skipping\n", | 1171 | "bitstream payload: %d, skipping\n", |
1058 | coda_get_bitstream_payload(ctx)); | 1172 | coda_get_bitstream_payload(ctx)); |
1059 | schedule_work(&ctx->skip_run); | 1173 | v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx); |
1060 | return -EAGAIN; | 1174 | return -EAGAIN; |
1061 | } | 1175 | } |
1062 | 1176 | ||
@@ -1065,13 +1179,16 @@ static int coda_prepare_decode(struct coda_ctx *ctx) | |||
1065 | int ret = coda_start_decoding(ctx); | 1179 | int ret = coda_start_decoding(ctx); |
1066 | if (ret < 0) { | 1180 | if (ret < 0) { |
1067 | v4l2_err(&dev->v4l2_dev, "failed to start decoding\n"); | 1181 | v4l2_err(&dev->v4l2_dev, "failed to start decoding\n"); |
1068 | schedule_work(&ctx->skip_run); | 1182 | v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx); |
1069 | return -EAGAIN; | 1183 | return -EAGAIN; |
1070 | } else { | 1184 | } else { |
1071 | ctx->initialized = 1; | 1185 | ctx->initialized = 1; |
1072 | } | 1186 | } |
1073 | } | 1187 | } |
1074 | 1188 | ||
1189 | if (dev->devtype->product == CODA_960) | ||
1190 | coda_set_gdi_regs(ctx); | ||
1191 | |||
1075 | /* Set rotator output */ | 1192 | /* Set rotator output */ |
1076 | picture_y = vb2_dma_contig_plane_dma_addr(dst_buf, 0); | 1193 | picture_y = vb2_dma_contig_plane_dma_addr(dst_buf, 0); |
1077 | if (q_data_dst->fourcc == V4L2_PIX_FMT_YVU420) { | 1194 | if (q_data_dst->fourcc == V4L2_PIX_FMT_YVU420) { |
@@ -1082,10 +1199,26 @@ static int coda_prepare_decode(struct coda_ctx *ctx) | |||
1082 | picture_cb = picture_y + stridey * height; | 1199 | picture_cb = picture_y + stridey * height; |
1083 | picture_cr = picture_cb + stridey / 2 * height / 2; | 1200 | picture_cr = picture_cb + stridey / 2 * height / 2; |
1084 | } | 1201 | } |
1085 | coda_write(dev, picture_y, CODA_CMD_DEC_PIC_ROT_ADDR_Y); | 1202 | |
1086 | coda_write(dev, picture_cb, CODA_CMD_DEC_PIC_ROT_ADDR_CB); | 1203 | if (dev->devtype->product == CODA_960) { |
1087 | coda_write(dev, picture_cr, CODA_CMD_DEC_PIC_ROT_ADDR_CR); | 1204 | /* |
1088 | coda_write(dev, stridey, CODA_CMD_DEC_PIC_ROT_STRIDE); | 1205 | * The CODA960 seems to have an internal list of buffers with |
1206 | * 64 entries that includes the registered frame buffers as | ||
1207 | * well as the rotator buffer output. | ||
1208 | * ROT_INDEX needs to be < 0x40, but > ctx->num_internal_frames. | ||
1209 | */ | ||
1210 | coda_write(dev, CODA_MAX_FRAMEBUFFERS + dst_buf->v4l2_buf.index, | ||
1211 | CODA9_CMD_DEC_PIC_ROT_INDEX); | ||
1212 | coda_write(dev, picture_y, CODA9_CMD_DEC_PIC_ROT_ADDR_Y); | ||
1213 | coda_write(dev, picture_cb, CODA9_CMD_DEC_PIC_ROT_ADDR_CB); | ||
1214 | coda_write(dev, picture_cr, CODA9_CMD_DEC_PIC_ROT_ADDR_CR); | ||
1215 | coda_write(dev, stridey, CODA9_CMD_DEC_PIC_ROT_STRIDE); | ||
1216 | } else { | ||
1217 | coda_write(dev, picture_y, CODA_CMD_DEC_PIC_ROT_ADDR_Y); | ||
1218 | coda_write(dev, picture_cb, CODA_CMD_DEC_PIC_ROT_ADDR_CB); | ||
1219 | coda_write(dev, picture_cr, CODA_CMD_DEC_PIC_ROT_ADDR_CR); | ||
1220 | coda_write(dev, stridey, CODA_CMD_DEC_PIC_ROT_STRIDE); | ||
1221 | } | ||
1089 | coda_write(dev, CODA_ROT_MIR_ENABLE | ctx->params.rot_mode, | 1222 | coda_write(dev, CODA_ROT_MIR_ENABLE | ctx->params.rot_mode, |
1090 | CODA_CMD_DEC_PIC_ROT_MODE); | 1223 | CODA_CMD_DEC_PIC_ROT_MODE); |
1091 | 1224 | ||
@@ -1095,6 +1228,9 @@ static int coda_prepare_decode(struct coda_ctx *ctx) | |||
1095 | case CODA_7541: | 1228 | case CODA_7541: |
1096 | coda_write(dev, CODA_PRE_SCAN_EN, CODA_CMD_DEC_PIC_OPTION); | 1229 | coda_write(dev, CODA_PRE_SCAN_EN, CODA_CMD_DEC_PIC_OPTION); |
1097 | break; | 1230 | break; |
1231 | case CODA_960: | ||
1232 | coda_write(dev, (1 << 10), CODA_CMD_DEC_PIC_OPTION); /* 'hardcode to use interrupt disable mode'? */ | ||
1233 | break; | ||
1098 | } | 1234 | } |
1099 | 1235 | ||
1100 | coda_write(dev, 0, CODA_CMD_DEC_PIC_SKIP_NUM); | 1236 | coda_write(dev, 0, CODA_CMD_DEC_PIC_SKIP_NUM); |
@@ -1116,8 +1252,8 @@ static void coda_prepare_encode(struct coda_ctx *ctx) | |||
1116 | u32 pic_stream_buffer_addr, pic_stream_buffer_size; | 1252 | u32 pic_stream_buffer_addr, pic_stream_buffer_size; |
1117 | u32 dst_fourcc; | 1253 | u32 dst_fourcc; |
1118 | 1254 | ||
1119 | src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); | 1255 | src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); |
1120 | dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); | 1256 | dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); |
1121 | q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | 1257 | q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); |
1122 | q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); | 1258 | q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); |
1123 | dst_fourcc = q_data_dst->fourcc; | 1259 | dst_fourcc = q_data_dst->fourcc; |
@@ -1139,6 +1275,9 @@ static void coda_prepare_encode(struct coda_ctx *ctx) | |||
1139 | src_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_PFRAME; | 1275 | src_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_PFRAME; |
1140 | } | 1276 | } |
1141 | 1277 | ||
1278 | if (dev->devtype->product == CODA_960) | ||
1279 | coda_set_gdi_regs(ctx); | ||
1280 | |||
1142 | /* | 1281 | /* |
1143 | * Copy headers at the beginning of the first frame for H.264 only. | 1282 | * Copy headers at the beginning of the first frame for H.264 only. |
1144 | * In MPEG4 they are already copied by the coda. | 1283 | * In MPEG4 they are already copied by the coda. |
@@ -1205,51 +1344,93 @@ static void coda_prepare_encode(struct coda_ctx *ctx) | |||
1205 | switch (q_data_src->fourcc) { | 1344 | switch (q_data_src->fourcc) { |
1206 | case V4L2_PIX_FMT_YVU420: | 1345 | case V4L2_PIX_FMT_YVU420: |
1207 | /* Switch Cb and Cr for YVU420 format */ | 1346 | /* Switch Cb and Cr for YVU420 format */ |
1208 | picture_cr = picture_y + q_data_src->width * q_data_src->height; | 1347 | picture_cr = picture_y + q_data_src->bytesperline * |
1209 | picture_cb = picture_cr + q_data_src->width / 2 * | 1348 | q_data_src->height; |
1349 | picture_cb = picture_cr + q_data_src->bytesperline / 2 * | ||
1210 | q_data_src->height / 2; | 1350 | q_data_src->height / 2; |
1211 | break; | 1351 | break; |
1212 | case V4L2_PIX_FMT_YUV420: | 1352 | case V4L2_PIX_FMT_YUV420: |
1213 | default: | 1353 | default: |
1214 | picture_cb = picture_y + q_data_src->width * q_data_src->height; | 1354 | picture_cb = picture_y + q_data_src->bytesperline * |
1215 | picture_cr = picture_cb + q_data_src->width / 2 * | 1355 | q_data_src->height; |
1356 | picture_cr = picture_cb + q_data_src->bytesperline / 2 * | ||
1216 | q_data_src->height / 2; | 1357 | q_data_src->height / 2; |
1217 | break; | 1358 | break; |
1218 | } | 1359 | } |
1219 | 1360 | ||
1220 | coda_write(dev, picture_y, CODA_CMD_ENC_PIC_SRC_ADDR_Y); | 1361 | if (dev->devtype->product == CODA_960) { |
1221 | coda_write(dev, picture_cb, CODA_CMD_ENC_PIC_SRC_ADDR_CB); | 1362 | coda_write(dev, 4/*FIXME: 0*/, CODA9_CMD_ENC_PIC_SRC_INDEX); |
1222 | coda_write(dev, picture_cr, CODA_CMD_ENC_PIC_SRC_ADDR_CR); | 1363 | coda_write(dev, q_data_src->width, CODA9_CMD_ENC_PIC_SRC_STRIDE); |
1364 | coda_write(dev, 0, CODA9_CMD_ENC_PIC_SUB_FRAME_SYNC); | ||
1365 | |||
1366 | coda_write(dev, picture_y, CODA9_CMD_ENC_PIC_SRC_ADDR_Y); | ||
1367 | coda_write(dev, picture_cb, CODA9_CMD_ENC_PIC_SRC_ADDR_CB); | ||
1368 | coda_write(dev, picture_cr, CODA9_CMD_ENC_PIC_SRC_ADDR_CR); | ||
1369 | } else { | ||
1370 | coda_write(dev, picture_y, CODA_CMD_ENC_PIC_SRC_ADDR_Y); | ||
1371 | coda_write(dev, picture_cb, CODA_CMD_ENC_PIC_SRC_ADDR_CB); | ||
1372 | coda_write(dev, picture_cr, CODA_CMD_ENC_PIC_SRC_ADDR_CR); | ||
1373 | } | ||
1223 | coda_write(dev, force_ipicture << 1 & 0x2, | 1374 | coda_write(dev, force_ipicture << 1 & 0x2, |
1224 | CODA_CMD_ENC_PIC_OPTION); | 1375 | CODA_CMD_ENC_PIC_OPTION); |
1225 | 1376 | ||
1226 | coda_write(dev, pic_stream_buffer_addr, CODA_CMD_ENC_PIC_BB_START); | 1377 | coda_write(dev, pic_stream_buffer_addr, CODA_CMD_ENC_PIC_BB_START); |
1227 | coda_write(dev, pic_stream_buffer_size / 1024, | 1378 | coda_write(dev, pic_stream_buffer_size / 1024, |
1228 | CODA_CMD_ENC_PIC_BB_SIZE); | 1379 | CODA_CMD_ENC_PIC_BB_SIZE); |
1380 | |||
1381 | if (!ctx->streamon_out) { | ||
1382 | /* After streamoff on the output side, set the stream end flag */ | ||
1383 | ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG; | ||
1384 | coda_write(dev, ctx->bit_stream_param, CODA_REG_BIT_BIT_STREAM_PARAM); | ||
1385 | } | ||
1229 | } | 1386 | } |
1230 | 1387 | ||
1231 | static void coda_device_run(void *m2m_priv) | 1388 | static void coda_device_run(void *m2m_priv) |
1232 | { | 1389 | { |
1233 | struct coda_ctx *ctx = m2m_priv; | 1390 | struct coda_ctx *ctx = m2m_priv; |
1234 | struct coda_dev *dev = ctx->dev; | 1391 | struct coda_dev *dev = ctx->dev; |
1235 | int ret; | 1392 | |
1393 | queue_work(dev->workqueue, &ctx->pic_run_work); | ||
1394 | } | ||
1395 | |||
1396 | static void coda_free_framebuffers(struct coda_ctx *ctx); | ||
1397 | static void coda_free_context_buffers(struct coda_ctx *ctx); | ||
1398 | |||
1399 | static void coda_seq_end_work(struct work_struct *work) | ||
1400 | { | ||
1401 | struct coda_ctx *ctx = container_of(work, struct coda_ctx, seq_end_work); | ||
1402 | struct coda_dev *dev = ctx->dev; | ||
1236 | 1403 | ||
1237 | mutex_lock(&ctx->buffer_mutex); | 1404 | mutex_lock(&ctx->buffer_mutex); |
1405 | mutex_lock(&dev->coda_mutex); | ||
1238 | 1406 | ||
1239 | /* | 1407 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, |
1240 | * If streamoff dequeued all buffers before we could get the lock, | 1408 | "%d: %s: sent command 'SEQ_END' to coda\n", ctx->idx, __func__); |
1241 | * just bail out immediately. | 1409 | if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) { |
1242 | */ | 1410 | v4l2_err(&dev->v4l2_dev, |
1243 | if ((!v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) && | 1411 | "CODA_COMMAND_SEQ_END failed\n"); |
1244 | ctx->inst_type != CODA_INST_DECODER) || | ||
1245 | !v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx)) { | ||
1246 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, | ||
1247 | "%d: device_run without buffers\n", ctx->idx); | ||
1248 | mutex_unlock(&ctx->buffer_mutex); | ||
1249 | schedule_work(&ctx->skip_run); | ||
1250 | return; | ||
1251 | } | 1412 | } |
1252 | 1413 | ||
1414 | kfifo_init(&ctx->bitstream_fifo, | ||
1415 | ctx->bitstream.vaddr, ctx->bitstream.size); | ||
1416 | |||
1417 | coda_free_framebuffers(ctx); | ||
1418 | coda_free_context_buffers(ctx); | ||
1419 | |||
1420 | mutex_unlock(&dev->coda_mutex); | ||
1421 | mutex_unlock(&ctx->buffer_mutex); | ||
1422 | } | ||
1423 | |||
1424 | static void coda_finish_decode(struct coda_ctx *ctx); | ||
1425 | static void coda_finish_encode(struct coda_ctx *ctx); | ||
1426 | |||
1427 | static void coda_pic_run_work(struct work_struct *work) | ||
1428 | { | ||
1429 | struct coda_ctx *ctx = container_of(work, struct coda_ctx, pic_run_work); | ||
1430 | struct coda_dev *dev = ctx->dev; | ||
1431 | int ret; | ||
1432 | |||
1433 | mutex_lock(&ctx->buffer_mutex); | ||
1253 | mutex_lock(&dev->coda_mutex); | 1434 | mutex_lock(&dev->coda_mutex); |
1254 | 1435 | ||
1255 | if (ctx->inst_type == CODA_INST_DECODER) { | 1436 | if (ctx->inst_type == CODA_INST_DECODER) { |
@@ -1268,12 +1449,30 @@ static void coda_device_run(void *m2m_priv) | |||
1268 | coda_write(dev, ctx->iram_info.axi_sram_use, | 1449 | coda_write(dev, ctx->iram_info.axi_sram_use, |
1269 | CODA7_REG_BIT_AXI_SRAM_USE); | 1450 | CODA7_REG_BIT_AXI_SRAM_USE); |
1270 | 1451 | ||
1271 | /* 1 second timeout in case CODA locks up */ | ||
1272 | schedule_delayed_work(&dev->timeout, HZ); | ||
1273 | |||
1274 | if (ctx->inst_type == CODA_INST_DECODER) | 1452 | if (ctx->inst_type == CODA_INST_DECODER) |
1275 | coda_kfifo_sync_to_device_full(ctx); | 1453 | coda_kfifo_sync_to_device_full(ctx); |
1276 | coda_command_async(ctx, CODA_COMMAND_PIC_RUN); | 1454 | coda_command_async(ctx, CODA_COMMAND_PIC_RUN); |
1455 | |||
1456 | if (!wait_for_completion_timeout(&ctx->completion, msecs_to_jiffies(1000))) { | ||
1457 | dev_err(&dev->plat_dev->dev, "CODA PIC_RUN timeout\n"); | ||
1458 | |||
1459 | ctx->hold = true; | ||
1460 | |||
1461 | coda_hw_reset(ctx); | ||
1462 | } else if (!ctx->aborting) { | ||
1463 | if (ctx->inst_type == CODA_INST_DECODER) | ||
1464 | coda_finish_decode(ctx); | ||
1465 | else | ||
1466 | coda_finish_encode(ctx); | ||
1467 | } | ||
1468 | |||
1469 | if (ctx->aborting || (!ctx->streamon_cap && !ctx->streamon_out)) | ||
1470 | queue_work(dev->workqueue, &ctx->seq_end_work); | ||
1471 | |||
1472 | mutex_unlock(&dev->coda_mutex); | ||
1473 | mutex_unlock(&ctx->buffer_mutex); | ||
1474 | |||
1475 | v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx); | ||
1277 | } | 1476 | } |
1278 | 1477 | ||
1279 | static int coda_job_ready(void *m2m_priv) | 1478 | static int coda_job_ready(void *m2m_priv) |
@@ -1285,20 +1484,20 @@ static int coda_job_ready(void *m2m_priv) | |||
1285 | * and 1 frame are needed. In the decoder case, | 1484 | * and 1 frame are needed. In the decoder case, |
1286 | * the compressed frame can be in the bitstream. | 1485 | * the compressed frame can be in the bitstream. |
1287 | */ | 1486 | */ |
1288 | if (!v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) && | 1487 | if (!v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) && |
1289 | ctx->inst_type != CODA_INST_DECODER) { | 1488 | ctx->inst_type != CODA_INST_DECODER) { |
1290 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, | 1489 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, |
1291 | "not ready: not enough video buffers.\n"); | 1490 | "not ready: not enough video buffers.\n"); |
1292 | return 0; | 1491 | return 0; |
1293 | } | 1492 | } |
1294 | 1493 | ||
1295 | if (!v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx)) { | 1494 | if (!v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx)) { |
1296 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, | 1495 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, |
1297 | "not ready: not enough video capture buffers.\n"); | 1496 | "not ready: not enough video capture buffers.\n"); |
1298 | return 0; | 1497 | return 0; |
1299 | } | 1498 | } |
1300 | 1499 | ||
1301 | if (ctx->prescan_failed || | 1500 | if (ctx->hold || |
1302 | ((ctx->inst_type == CODA_INST_DECODER) && | 1501 | ((ctx->inst_type == CODA_INST_DECODER) && |
1303 | (coda_get_bitstream_payload(ctx) < 512) && | 1502 | (coda_get_bitstream_payload(ctx) < 512) && |
1304 | !(ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG))) { | 1503 | !(ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG))) { |
@@ -1351,6 +1550,32 @@ static struct v4l2_m2m_ops coda_m2m_ops = { | |||
1351 | .unlock = coda_unlock, | 1550 | .unlock = coda_unlock, |
1352 | }; | 1551 | }; |
1353 | 1552 | ||
1553 | static void coda_set_tiled_map_type(struct coda_ctx *ctx, int tiled_map_type) | ||
1554 | { | ||
1555 | struct gdi_tiled_map *tiled_map = &ctx->tiled_map; | ||
1556 | int luma_map, chro_map, i; | ||
1557 | |||
1558 | memset(tiled_map, 0, sizeof(*tiled_map)); | ||
1559 | |||
1560 | luma_map = 64; | ||
1561 | chro_map = 64; | ||
1562 | tiled_map->map_type = tiled_map_type; | ||
1563 | for (i = 0; i < 16; i++) | ||
1564 | tiled_map->xy2ca_map[i] = luma_map << 8 | chro_map; | ||
1565 | for (i = 0; i < 4; i++) | ||
1566 | tiled_map->xy2ba_map[i] = luma_map << 8 | chro_map; | ||
1567 | for (i = 0; i < 16; i++) | ||
1568 | tiled_map->xy2ra_map[i] = luma_map << 8 | chro_map; | ||
1569 | |||
1570 | if (tiled_map_type == GDI_LINEAR_FRAME_MAP) { | ||
1571 | tiled_map->xy2rbc_config = 0; | ||
1572 | } else { | ||
1573 | dev_err(&ctx->dev->plat_dev->dev, "invalid map type: %d\n", | ||
1574 | tiled_map_type); | ||
1575 | return; | ||
1576 | } | ||
1577 | } | ||
1578 | |||
1354 | static void set_default_params(struct coda_ctx *ctx) | 1579 | static void set_default_params(struct coda_ctx *ctx) |
1355 | { | 1580 | { |
1356 | int max_w; | 1581 | int max_w; |
@@ -1370,10 +1595,19 @@ static void set_default_params(struct coda_ctx *ctx) | |||
1370 | ctx->q_data[V4L2_M2M_DST].fourcc = ctx->codec->dst_fourcc; | 1595 | ctx->q_data[V4L2_M2M_DST].fourcc = ctx->codec->dst_fourcc; |
1371 | ctx->q_data[V4L2_M2M_SRC].width = max_w; | 1596 | ctx->q_data[V4L2_M2M_SRC].width = max_w; |
1372 | ctx->q_data[V4L2_M2M_SRC].height = max_h; | 1597 | ctx->q_data[V4L2_M2M_SRC].height = max_h; |
1598 | ctx->q_data[V4L2_M2M_SRC].bytesperline = max_w; | ||
1373 | ctx->q_data[V4L2_M2M_SRC].sizeimage = (max_w * max_h * 3) / 2; | 1599 | ctx->q_data[V4L2_M2M_SRC].sizeimage = (max_w * max_h * 3) / 2; |
1374 | ctx->q_data[V4L2_M2M_DST].width = max_w; | 1600 | ctx->q_data[V4L2_M2M_DST].width = max_w; |
1375 | ctx->q_data[V4L2_M2M_DST].height = max_h; | 1601 | ctx->q_data[V4L2_M2M_DST].height = max_h; |
1602 | ctx->q_data[V4L2_M2M_DST].bytesperline = 0; | ||
1376 | ctx->q_data[V4L2_M2M_DST].sizeimage = CODA_MAX_FRAME_SIZE; | 1603 | ctx->q_data[V4L2_M2M_DST].sizeimage = CODA_MAX_FRAME_SIZE; |
1604 | ctx->q_data[V4L2_M2M_SRC].rect.width = max_w; | ||
1605 | ctx->q_data[V4L2_M2M_SRC].rect.height = max_h; | ||
1606 | ctx->q_data[V4L2_M2M_DST].rect.width = max_w; | ||
1607 | ctx->q_data[V4L2_M2M_DST].rect.height = max_h; | ||
1608 | |||
1609 | if (ctx->dev->devtype->product == CODA_960) | ||
1610 | coda_set_tiled_map_type(ctx, GDI_LINEAR_FRAME_MAP); | ||
1377 | } | 1611 | } |
1378 | 1612 | ||
1379 | /* | 1613 | /* |
@@ -1423,6 +1657,7 @@ static int coda_buf_prepare(struct vb2_buffer *vb) | |||
1423 | static void coda_buf_queue(struct vb2_buffer *vb) | 1657 | static void coda_buf_queue(struct vb2_buffer *vb) |
1424 | { | 1658 | { |
1425 | struct coda_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); | 1659 | struct coda_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); |
1660 | struct coda_dev *dev = ctx->dev; | ||
1426 | struct coda_q_data *q_data; | 1661 | struct coda_q_data *q_data; |
1427 | 1662 | ||
1428 | q_data = get_q_data(ctx, vb->vb2_queue->type); | 1663 | q_data = get_q_data(ctx, vb->vb2_queue->type); |
@@ -1437,29 +1672,24 @@ static void coda_buf_queue(struct vb2_buffer *vb) | |||
1437 | * For backwards compatibility, queuing an empty buffer marks | 1672 | * For backwards compatibility, queuing an empty buffer marks |
1438 | * the stream end | 1673 | * the stream end |
1439 | */ | 1674 | */ |
1440 | if (vb2_get_plane_payload(vb, 0) == 0) | 1675 | if (vb2_get_plane_payload(vb, 0) == 0) { |
1441 | ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG; | 1676 | ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG; |
1677 | if ((dev->devtype->product == CODA_960) && | ||
1678 | coda_isbusy(dev) && | ||
1679 | (ctx->idx == coda_read(dev, CODA_REG_BIT_RUN_INDEX))) { | ||
1680 | /* if this decoder instance is running, set the stream end flag */ | ||
1681 | coda_write(dev, ctx->bit_stream_param, CODA_REG_BIT_BIT_STREAM_PARAM); | ||
1682 | } | ||
1683 | } | ||
1442 | mutex_lock(&ctx->bitstream_mutex); | 1684 | mutex_lock(&ctx->bitstream_mutex); |
1443 | v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); | 1685 | v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb); |
1444 | coda_fill_bitstream(ctx); | 1686 | coda_fill_bitstream(ctx); |
1445 | mutex_unlock(&ctx->bitstream_mutex); | 1687 | mutex_unlock(&ctx->bitstream_mutex); |
1446 | } else { | 1688 | } else { |
1447 | v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); | 1689 | v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb); |
1448 | } | 1690 | } |
1449 | } | 1691 | } |
1450 | 1692 | ||
1451 | static void coda_wait_prepare(struct vb2_queue *q) | ||
1452 | { | ||
1453 | struct coda_ctx *ctx = vb2_get_drv_priv(q); | ||
1454 | coda_unlock(ctx); | ||
1455 | } | ||
1456 | |||
1457 | static void coda_wait_finish(struct vb2_queue *q) | ||
1458 | { | ||
1459 | struct coda_ctx *ctx = vb2_get_drv_priv(q); | ||
1460 | coda_lock(ctx); | ||
1461 | } | ||
1462 | |||
1463 | static void coda_parabuf_write(struct coda_ctx *ctx, int index, u32 value) | 1693 | static void coda_parabuf_write(struct coda_ctx *ctx, int index, u32 value) |
1464 | { | 1694 | { |
1465 | struct coda_dev *dev = ctx->dev; | 1695 | struct coda_dev *dev = ctx->dev; |
@@ -1472,7 +1702,8 @@ static void coda_parabuf_write(struct coda_ctx *ctx, int index, u32 value) | |||
1472 | } | 1702 | } |
1473 | 1703 | ||
1474 | static int coda_alloc_aux_buf(struct coda_dev *dev, | 1704 | static int coda_alloc_aux_buf(struct coda_dev *dev, |
1475 | struct coda_aux_buf *buf, size_t size) | 1705 | struct coda_aux_buf *buf, size_t size, |
1706 | const char *name, struct dentry *parent) | ||
1476 | { | 1707 | { |
1477 | buf->vaddr = dma_alloc_coherent(&dev->plat_dev->dev, size, &buf->paddr, | 1708 | buf->vaddr = dma_alloc_coherent(&dev->plat_dev->dev, size, &buf->paddr, |
1478 | GFP_KERNEL); | 1709 | GFP_KERNEL); |
@@ -1481,13 +1712,23 @@ static int coda_alloc_aux_buf(struct coda_dev *dev, | |||
1481 | 1712 | ||
1482 | buf->size = size; | 1713 | buf->size = size; |
1483 | 1714 | ||
1715 | if (name && parent) { | ||
1716 | buf->blob.data = buf->vaddr; | ||
1717 | buf->blob.size = size; | ||
1718 | buf->dentry = debugfs_create_blob(name, 0644, parent, &buf->blob); | ||
1719 | if (!buf->dentry) | ||
1720 | dev_warn(&dev->plat_dev->dev, | ||
1721 | "failed to create debugfs entry %s\n", name); | ||
1722 | } | ||
1723 | |||
1484 | return 0; | 1724 | return 0; |
1485 | } | 1725 | } |
1486 | 1726 | ||
1487 | static inline int coda_alloc_context_buf(struct coda_ctx *ctx, | 1727 | static inline int coda_alloc_context_buf(struct coda_ctx *ctx, |
1488 | struct coda_aux_buf *buf, size_t size) | 1728 | struct coda_aux_buf *buf, size_t size, |
1729 | const char *name) | ||
1489 | { | 1730 | { |
1490 | return coda_alloc_aux_buf(ctx->dev, buf, size); | 1731 | return coda_alloc_aux_buf(ctx->dev, buf, size, name, ctx->debugfs_entry); |
1491 | } | 1732 | } |
1492 | 1733 | ||
1493 | static void coda_free_aux_buf(struct coda_dev *dev, | 1734 | static void coda_free_aux_buf(struct coda_dev *dev, |
@@ -1499,6 +1740,7 @@ static void coda_free_aux_buf(struct coda_dev *dev, | |||
1499 | buf->vaddr = NULL; | 1740 | buf->vaddr = NULL; |
1500 | buf->size = 0; | 1741 | buf->size = 0; |
1501 | } | 1742 | } |
1743 | debugfs_remove(buf->dentry); | ||
1502 | } | 1744 | } |
1503 | 1745 | ||
1504 | static void coda_free_framebuffers(struct coda_ctx *ctx) | 1746 | static void coda_free_framebuffers(struct coda_ctx *ctx) |
@@ -1512,25 +1754,35 @@ static void coda_free_framebuffers(struct coda_ctx *ctx) | |||
1512 | static int coda_alloc_framebuffers(struct coda_ctx *ctx, struct coda_q_data *q_data, u32 fourcc) | 1754 | static int coda_alloc_framebuffers(struct coda_ctx *ctx, struct coda_q_data *q_data, u32 fourcc) |
1513 | { | 1755 | { |
1514 | struct coda_dev *dev = ctx->dev; | 1756 | struct coda_dev *dev = ctx->dev; |
1515 | int height = q_data->height; | 1757 | int width, height; |
1516 | dma_addr_t paddr; | 1758 | dma_addr_t paddr; |
1517 | int ysize; | 1759 | int ysize; |
1518 | int ret; | 1760 | int ret; |
1519 | int i; | 1761 | int i; |
1520 | 1762 | ||
1521 | if (ctx->codec && ctx->codec->src_fourcc == V4L2_PIX_FMT_H264) | 1763 | if (ctx->codec && (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 || |
1522 | height = round_up(height, 16); | 1764 | ctx->codec->dst_fourcc == V4L2_PIX_FMT_H264)) { |
1523 | ysize = round_up(q_data->width, 8) * height; | 1765 | width = round_up(q_data->width, 16); |
1766 | height = round_up(q_data->height, 16); | ||
1767 | } else { | ||
1768 | width = round_up(q_data->width, 8); | ||
1769 | height = q_data->height; | ||
1770 | } | ||
1771 | ysize = width * height; | ||
1524 | 1772 | ||
1525 | /* Allocate frame buffers */ | 1773 | /* Allocate frame buffers */ |
1526 | for (i = 0; i < ctx->num_internal_frames; i++) { | 1774 | for (i = 0; i < ctx->num_internal_frames; i++) { |
1527 | size_t size; | 1775 | size_t size; |
1776 | char *name; | ||
1528 | 1777 | ||
1529 | size = q_data->sizeimage; | 1778 | size = ysize + ysize / 2; |
1530 | if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 && | 1779 | if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 && |
1531 | dev->devtype->product != CODA_DX6) | 1780 | dev->devtype->product != CODA_DX6) |
1532 | ctx->internal_frames[i].size += ysize/4; | 1781 | size += ysize / 4; |
1533 | ret = coda_alloc_context_buf(ctx, &ctx->internal_frames[i], size); | 1782 | name = kasprintf(GFP_KERNEL, "fb%d", i); |
1783 | ret = coda_alloc_context_buf(ctx, &ctx->internal_frames[i], | ||
1784 | size, name); | ||
1785 | kfree(name); | ||
1534 | if (ret < 0) { | 1786 | if (ret < 0) { |
1535 | coda_free_framebuffers(ctx); | 1787 | coda_free_framebuffers(ctx); |
1536 | return ret; | 1788 | return ret; |
@@ -1579,23 +1831,48 @@ static int coda_h264_padding(int size, char *p) | |||
1579 | return nal_size; | 1831 | return nal_size; |
1580 | } | 1832 | } |
1581 | 1833 | ||
1834 | static phys_addr_t coda_iram_alloc(struct coda_iram_info *iram, size_t size) | ||
1835 | { | ||
1836 | phys_addr_t ret; | ||
1837 | |||
1838 | size = round_up(size, 1024); | ||
1839 | if (size > iram->remaining) | ||
1840 | return 0; | ||
1841 | iram->remaining -= size; | ||
1842 | |||
1843 | ret = iram->next_paddr; | ||
1844 | iram->next_paddr += size; | ||
1845 | |||
1846 | return ret; | ||
1847 | } | ||
1848 | |||
1582 | static void coda_setup_iram(struct coda_ctx *ctx) | 1849 | static void coda_setup_iram(struct coda_ctx *ctx) |
1583 | { | 1850 | { |
1584 | struct coda_iram_info *iram_info = &ctx->iram_info; | 1851 | struct coda_iram_info *iram_info = &ctx->iram_info; |
1585 | struct coda_dev *dev = ctx->dev; | 1852 | struct coda_dev *dev = ctx->dev; |
1586 | int ipacdc_size; | ||
1587 | int bitram_size; | ||
1588 | int dbk_size; | ||
1589 | int ovl_size; | ||
1590 | int mb_width; | 1853 | int mb_width; |
1591 | int me_size; | 1854 | int dbk_bits; |
1592 | int size; | 1855 | int bit_bits; |
1856 | int ip_bits; | ||
1593 | 1857 | ||
1594 | memset(iram_info, 0, sizeof(*iram_info)); | 1858 | memset(iram_info, 0, sizeof(*iram_info)); |
1595 | size = dev->iram_size; | 1859 | iram_info->next_paddr = dev->iram.paddr; |
1860 | iram_info->remaining = dev->iram.size; | ||
1596 | 1861 | ||
1597 | if (dev->devtype->product == CODA_DX6) | 1862 | switch (dev->devtype->product) { |
1863 | case CODA_7541: | ||
1864 | dbk_bits = CODA7_USE_HOST_DBK_ENABLE | CODA7_USE_DBK_ENABLE; | ||
1865 | bit_bits = CODA7_USE_HOST_BIT_ENABLE | CODA7_USE_BIT_ENABLE; | ||
1866 | ip_bits = CODA7_USE_HOST_IP_ENABLE | CODA7_USE_IP_ENABLE; | ||
1867 | break; | ||
1868 | case CODA_960: | ||
1869 | dbk_bits = CODA9_USE_HOST_DBK_ENABLE | CODA9_USE_DBK_ENABLE; | ||
1870 | bit_bits = CODA9_USE_HOST_BIT_ENABLE | CODA7_USE_BIT_ENABLE; | ||
1871 | ip_bits = CODA9_USE_HOST_IP_ENABLE | CODA7_USE_IP_ENABLE; | ||
1872 | break; | ||
1873 | default: /* CODA_DX6 */ | ||
1598 | return; | 1874 | return; |
1875 | } | ||
1599 | 1876 | ||
1600 | if (ctx->inst_type == CODA_INST_ENCODER) { | 1877 | if (ctx->inst_type == CODA_INST_ENCODER) { |
1601 | struct coda_q_data *q_data_src; | 1878 | struct coda_q_data *q_data_src; |
@@ -1604,111 +1881,63 @@ static void coda_setup_iram(struct coda_ctx *ctx) | |||
1604 | mb_width = DIV_ROUND_UP(q_data_src->width, 16); | 1881 | mb_width = DIV_ROUND_UP(q_data_src->width, 16); |
1605 | 1882 | ||
1606 | /* Prioritize in case IRAM is too small for everything */ | 1883 | /* Prioritize in case IRAM is too small for everything */ |
1607 | me_size = round_up(round_up(q_data_src->width, 16) * 36 + 2048, | 1884 | if (dev->devtype->product == CODA_7541) { |
1608 | 1024); | 1885 | iram_info->search_ram_size = round_up(mb_width * 16 * |
1609 | iram_info->search_ram_size = me_size; | 1886 | 36 + 2048, 1024); |
1610 | if (size >= iram_info->search_ram_size) { | 1887 | iram_info->search_ram_paddr = coda_iram_alloc(iram_info, |
1611 | if (dev->devtype->product == CODA_7541) | 1888 | iram_info->search_ram_size); |
1612 | iram_info->axi_sram_use |= CODA7_USE_HOST_ME_ENABLE; | 1889 | if (!iram_info->search_ram_paddr) { |
1613 | iram_info->search_ram_paddr = dev->iram_paddr; | 1890 | pr_err("IRAM is smaller than the search ram size\n"); |
1614 | size -= iram_info->search_ram_size; | 1891 | goto out; |
1615 | } else { | 1892 | } |
1616 | pr_err("IRAM is smaller than the search ram size\n"); | 1893 | iram_info->axi_sram_use |= CODA7_USE_HOST_ME_ENABLE | |
1617 | goto out; | 1894 | CODA7_USE_ME_ENABLE; |
1618 | } | 1895 | } |
1619 | 1896 | ||
1620 | /* Only H.264BP and H.263P3 are considered */ | 1897 | /* Only H.264BP and H.263P3 are considered */ |
1621 | dbk_size = round_up(128 * mb_width, 1024); | 1898 | iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, 64 * mb_width); |
1622 | if (size >= dbk_size) { | 1899 | iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, 64 * mb_width); |
1623 | iram_info->axi_sram_use |= CODA7_USE_HOST_DBK_ENABLE; | 1900 | if (!iram_info->buf_dbk_c_use) |
1624 | iram_info->buf_dbk_y_use = dev->iram_paddr + | ||
1625 | iram_info->search_ram_size; | ||
1626 | iram_info->buf_dbk_c_use = iram_info->buf_dbk_y_use + | ||
1627 | dbk_size / 2; | ||
1628 | size -= dbk_size; | ||
1629 | } else { | ||
1630 | goto out; | 1901 | goto out; |
1631 | } | 1902 | iram_info->axi_sram_use |= dbk_bits; |
1632 | 1903 | ||
1633 | bitram_size = round_up(128 * mb_width, 1024); | 1904 | iram_info->buf_bit_use = coda_iram_alloc(iram_info, 128 * mb_width); |
1634 | if (size >= bitram_size) { | 1905 | if (!iram_info->buf_bit_use) |
1635 | iram_info->axi_sram_use |= CODA7_USE_HOST_BIT_ENABLE; | ||
1636 | iram_info->buf_bit_use = iram_info->buf_dbk_c_use + | ||
1637 | dbk_size / 2; | ||
1638 | size -= bitram_size; | ||
1639 | } else { | ||
1640 | goto out; | 1906 | goto out; |
1641 | } | 1907 | iram_info->axi_sram_use |= bit_bits; |
1642 | 1908 | ||
1643 | ipacdc_size = round_up(128 * mb_width, 1024); | 1909 | iram_info->buf_ip_ac_dc_use = coda_iram_alloc(iram_info, 128 * mb_width); |
1644 | if (size >= ipacdc_size) { | 1910 | if (!iram_info->buf_ip_ac_dc_use) |
1645 | iram_info->axi_sram_use |= CODA7_USE_HOST_IP_ENABLE; | 1911 | goto out; |
1646 | iram_info->buf_ip_ac_dc_use = iram_info->buf_bit_use + | 1912 | iram_info->axi_sram_use |= ip_bits; |
1647 | bitram_size; | ||
1648 | size -= ipacdc_size; | ||
1649 | } | ||
1650 | 1913 | ||
1651 | /* OVL and BTP disabled for encoder */ | 1914 | /* OVL and BTP disabled for encoder */ |
1652 | } else if (ctx->inst_type == CODA_INST_DECODER) { | 1915 | } else if (ctx->inst_type == CODA_INST_DECODER) { |
1653 | struct coda_q_data *q_data_dst; | 1916 | struct coda_q_data *q_data_dst; |
1654 | int mb_height; | ||
1655 | 1917 | ||
1656 | q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); | 1918 | q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); |
1657 | mb_width = DIV_ROUND_UP(q_data_dst->width, 16); | 1919 | mb_width = DIV_ROUND_UP(q_data_dst->width, 16); |
1658 | mb_height = DIV_ROUND_UP(q_data_dst->height, 16); | 1920 | |
1659 | 1921 | iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, 128 * mb_width); | |
1660 | dbk_size = round_up(256 * mb_width, 1024); | 1922 | iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, 128 * mb_width); |
1661 | if (size >= dbk_size) { | 1923 | if (!iram_info->buf_dbk_c_use) |
1662 | iram_info->axi_sram_use |= CODA7_USE_HOST_DBK_ENABLE; | ||
1663 | iram_info->buf_dbk_y_use = dev->iram_paddr; | ||
1664 | iram_info->buf_dbk_c_use = dev->iram_paddr + | ||
1665 | dbk_size / 2; | ||
1666 | size -= dbk_size; | ||
1667 | } else { | ||
1668 | goto out; | 1924 | goto out; |
1669 | } | 1925 | iram_info->axi_sram_use |= dbk_bits; |
1670 | 1926 | ||
1671 | bitram_size = round_up(128 * mb_width, 1024); | 1927 | iram_info->buf_bit_use = coda_iram_alloc(iram_info, 128 * mb_width); |
1672 | if (size >= bitram_size) { | 1928 | if (!iram_info->buf_bit_use) |
1673 | iram_info->axi_sram_use |= CODA7_USE_HOST_BIT_ENABLE; | ||
1674 | iram_info->buf_bit_use = iram_info->buf_dbk_c_use + | ||
1675 | dbk_size / 2; | ||
1676 | size -= bitram_size; | ||
1677 | } else { | ||
1678 | goto out; | 1929 | goto out; |
1679 | } | 1930 | iram_info->axi_sram_use |= bit_bits; |
1680 | 1931 | ||
1681 | ipacdc_size = round_up(128 * mb_width, 1024); | 1932 | iram_info->buf_ip_ac_dc_use = coda_iram_alloc(iram_info, 128 * mb_width); |
1682 | if (size >= ipacdc_size) { | 1933 | if (!iram_info->buf_ip_ac_dc_use) |
1683 | iram_info->axi_sram_use |= CODA7_USE_HOST_IP_ENABLE; | ||
1684 | iram_info->buf_ip_ac_dc_use = iram_info->buf_bit_use + | ||
1685 | bitram_size; | ||
1686 | size -= ipacdc_size; | ||
1687 | } else { | ||
1688 | goto out; | 1934 | goto out; |
1689 | } | 1935 | iram_info->axi_sram_use |= ip_bits; |
1690 | 1936 | ||
1691 | ovl_size = round_up(80 * mb_width, 1024); | 1937 | /* OVL and BTP unused as there is no VC1 support yet */ |
1692 | } | 1938 | } |
1693 | 1939 | ||
1694 | out: | 1940 | out: |
1695 | switch (dev->devtype->product) { | ||
1696 | case CODA_DX6: | ||
1697 | break; | ||
1698 | case CODA_7541: | ||
1699 | /* i.MX53 uses secondary AXI for IRAM access */ | ||
1700 | if (iram_info->axi_sram_use & CODA7_USE_HOST_BIT_ENABLE) | ||
1701 | iram_info->axi_sram_use |= CODA7_USE_BIT_ENABLE; | ||
1702 | if (iram_info->axi_sram_use & CODA7_USE_HOST_IP_ENABLE) | ||
1703 | iram_info->axi_sram_use |= CODA7_USE_IP_ENABLE; | ||
1704 | if (iram_info->axi_sram_use & CODA7_USE_HOST_DBK_ENABLE) | ||
1705 | iram_info->axi_sram_use |= CODA7_USE_DBK_ENABLE; | ||
1706 | if (iram_info->axi_sram_use & CODA7_USE_HOST_OVL_ENABLE) | ||
1707 | iram_info->axi_sram_use |= CODA7_USE_OVL_ENABLE; | ||
1708 | if (iram_info->axi_sram_use & CODA7_USE_HOST_ME_ENABLE) | ||
1709 | iram_info->axi_sram_use |= CODA7_USE_ME_ENABLE; | ||
1710 | } | ||
1711 | |||
1712 | if (!(iram_info->axi_sram_use & CODA7_USE_HOST_IP_ENABLE)) | 1941 | if (!(iram_info->axi_sram_use & CODA7_USE_HOST_IP_ENABLE)) |
1713 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, | 1942 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, |
1714 | "IRAM smaller than needed\n"); | 1943 | "IRAM smaller than needed\n"); |
@@ -1746,13 +1975,8 @@ static int coda_alloc_context_buffers(struct coda_ctx *ctx, | |||
1746 | size_t size; | 1975 | size_t size; |
1747 | int ret; | 1976 | int ret; |
1748 | 1977 | ||
1749 | switch (dev->devtype->product) { | 1978 | if (dev->devtype->product == CODA_DX6) |
1750 | case CODA_7541: | ||
1751 | size = CODA7_WORK_BUF_SIZE; | ||
1752 | break; | ||
1753 | default: | ||
1754 | return 0; | 1979 | return 0; |
1755 | } | ||
1756 | 1980 | ||
1757 | if (ctx->psbuf.vaddr) { | 1981 | if (ctx->psbuf.vaddr) { |
1758 | v4l2_err(&dev->v4l2_dev, "psmembuf still allocated\n"); | 1982 | v4l2_err(&dev->v4l2_dev, "psmembuf still allocated\n"); |
@@ -1772,7 +1996,7 @@ static int coda_alloc_context_buffers(struct coda_ctx *ctx, | |||
1772 | /* worst case slice size */ | 1996 | /* worst case slice size */ |
1773 | size = (DIV_ROUND_UP(q_data->width, 16) * | 1997 | size = (DIV_ROUND_UP(q_data->width, 16) * |
1774 | DIV_ROUND_UP(q_data->height, 16)) * 3200 / 8 + 512; | 1998 | DIV_ROUND_UP(q_data->height, 16)) * 3200 / 8 + 512; |
1775 | ret = coda_alloc_context_buf(ctx, &ctx->slicebuf, size); | 1999 | ret = coda_alloc_context_buf(ctx, &ctx->slicebuf, size, "slicebuf"); |
1776 | if (ret < 0) { | 2000 | if (ret < 0) { |
1777 | v4l2_err(&dev->v4l2_dev, "failed to allocate %d byte slice buffer", | 2001 | v4l2_err(&dev->v4l2_dev, "failed to allocate %d byte slice buffer", |
1778 | ctx->slicebuf.size); | 2002 | ctx->slicebuf.size); |
@@ -1781,14 +2005,18 @@ static int coda_alloc_context_buffers(struct coda_ctx *ctx, | |||
1781 | } | 2005 | } |
1782 | 2006 | ||
1783 | if (dev->devtype->product == CODA_7541) { | 2007 | if (dev->devtype->product == CODA_7541) { |
1784 | ret = coda_alloc_context_buf(ctx, &ctx->psbuf, CODA7_PS_BUF_SIZE); | 2008 | ret = coda_alloc_context_buf(ctx, &ctx->psbuf, CODA7_PS_BUF_SIZE, "psbuf"); |
1785 | if (ret < 0) { | 2009 | if (ret < 0) { |
1786 | v4l2_err(&dev->v4l2_dev, "failed to allocate psmem buffer"); | 2010 | v4l2_err(&dev->v4l2_dev, "failed to allocate psmem buffer"); |
1787 | goto err; | 2011 | goto err; |
1788 | } | 2012 | } |
1789 | } | 2013 | } |
1790 | 2014 | ||
1791 | ret = coda_alloc_context_buf(ctx, &ctx->workbuf, size); | 2015 | size = dev->devtype->workbuf_size; |
2016 | if (dev->devtype->product == CODA_960 && | ||
2017 | q_data->fourcc == V4L2_PIX_FMT_H264) | ||
2018 | size += CODA9_PS_SAVE_SIZE; | ||
2019 | ret = coda_alloc_context_buf(ctx, &ctx->workbuf, size, "workbuf"); | ||
1792 | if (ret < 0) { | 2020 | if (ret < 0) { |
1793 | v4l2_err(&dev->v4l2_dev, "failed to allocate %d byte context buffer", | 2021 | v4l2_err(&dev->v4l2_dev, "failed to allocate %d byte context buffer", |
1794 | ctx->workbuf.size); | 2022 | ctx->workbuf.size); |
@@ -1834,12 +2062,17 @@ static int coda_start_decoding(struct coda_ctx *ctx) | |||
1834 | coda_write(dev, bitstream_buf, CODA_CMD_DEC_SEQ_BB_START); | 2062 | coda_write(dev, bitstream_buf, CODA_CMD_DEC_SEQ_BB_START); |
1835 | coda_write(dev, bitstream_size / 1024, CODA_CMD_DEC_SEQ_BB_SIZE); | 2063 | coda_write(dev, bitstream_size / 1024, CODA_CMD_DEC_SEQ_BB_SIZE); |
1836 | val = 0; | 2064 | val = 0; |
1837 | if (dev->devtype->product == CODA_7541) | 2065 | if ((dev->devtype->product == CODA_7541) || |
2066 | (dev->devtype->product == CODA_960)) | ||
1838 | val |= CODA_REORDER_ENABLE; | 2067 | val |= CODA_REORDER_ENABLE; |
1839 | coda_write(dev, val, CODA_CMD_DEC_SEQ_OPTION); | 2068 | coda_write(dev, val, CODA_CMD_DEC_SEQ_OPTION); |
1840 | 2069 | ||
1841 | ctx->params.codec_mode = ctx->codec->mode; | 2070 | ctx->params.codec_mode = ctx->codec->mode; |
1842 | ctx->params.codec_mode_aux = 0; | 2071 | if (dev->devtype->product == CODA_960 && |
2072 | src_fourcc == V4L2_PIX_FMT_MPEG4) | ||
2073 | ctx->params.codec_mode_aux = CODA_MP4_AUX_MPEG4; | ||
2074 | else | ||
2075 | ctx->params.codec_mode_aux = 0; | ||
1843 | if (src_fourcc == V4L2_PIX_FMT_H264) { | 2076 | if (src_fourcc == V4L2_PIX_FMT_H264) { |
1844 | if (dev->devtype->product == CODA_7541) { | 2077 | if (dev->devtype->product == CODA_7541) { |
1845 | coda_write(dev, ctx->psbuf.paddr, | 2078 | coda_write(dev, ctx->psbuf.paddr, |
@@ -1847,6 +2080,13 @@ static int coda_start_decoding(struct coda_ctx *ctx) | |||
1847 | coda_write(dev, (CODA7_PS_BUF_SIZE / 1024), | 2080 | coda_write(dev, (CODA7_PS_BUF_SIZE / 1024), |
1848 | CODA_CMD_DEC_SEQ_PS_BB_SIZE); | 2081 | CODA_CMD_DEC_SEQ_PS_BB_SIZE); |
1849 | } | 2082 | } |
2083 | if (dev->devtype->product == CODA_960) { | ||
2084 | coda_write(dev, 0, CODA_CMD_DEC_SEQ_X264_MV_EN); | ||
2085 | coda_write(dev, 512, CODA_CMD_DEC_SEQ_SPP_CHUNK_SIZE); | ||
2086 | } | ||
2087 | } | ||
2088 | if (dev->devtype->product != CODA_960) { | ||
2089 | coda_write(dev, 0, CODA_CMD_DEC_SEQ_SRC_SIZE); | ||
1850 | } | 2090 | } |
1851 | 2091 | ||
1852 | if (coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT)) { | 2092 | if (coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT)) { |
@@ -1888,7 +2128,7 @@ static int coda_start_decoding(struct coda_ctx *ctx) | |||
1888 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "%s instance %d now: %dx%d\n", | 2128 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "%s instance %d now: %dx%d\n", |
1889 | __func__, ctx->idx, width, height); | 2129 | __func__, ctx->idx, width, height); |
1890 | 2130 | ||
1891 | ctx->num_internal_frames = coda_read(dev, CODA_RET_DEC_SEQ_FRAME_NEED) + 1; | 2131 | ctx->num_internal_frames = coda_read(dev, CODA_RET_DEC_SEQ_FRAME_NEED); |
1892 | if (ctx->num_internal_frames > CODA_MAX_FRAMEBUFFERS) { | 2132 | if (ctx->num_internal_frames > CODA_MAX_FRAMEBUFFERS) { |
1893 | v4l2_err(&dev->v4l2_dev, | 2133 | v4l2_err(&dev->v4l2_dev, |
1894 | "not enough framebuffers to decode (%d < %d)\n", | 2134 | "not enough framebuffers to decode (%d < %d)\n", |
@@ -1896,6 +2136,21 @@ static int coda_start_decoding(struct coda_ctx *ctx) | |||
1896 | return -EINVAL; | 2136 | return -EINVAL; |
1897 | } | 2137 | } |
1898 | 2138 | ||
2139 | if (src_fourcc == V4L2_PIX_FMT_H264) { | ||
2140 | u32 left_right; | ||
2141 | u32 top_bottom; | ||
2142 | |||
2143 | left_right = coda_read(dev, CODA_RET_DEC_SEQ_CROP_LEFT_RIGHT); | ||
2144 | top_bottom = coda_read(dev, CODA_RET_DEC_SEQ_CROP_TOP_BOTTOM); | ||
2145 | |||
2146 | q_data_dst->rect.left = (left_right >> 10) & 0x3ff; | ||
2147 | q_data_dst->rect.top = (top_bottom >> 10) & 0x3ff; | ||
2148 | q_data_dst->rect.width = width - q_data_dst->rect.left - | ||
2149 | (left_right & 0x3ff); | ||
2150 | q_data_dst->rect.height = height - q_data_dst->rect.top - | ||
2151 | (top_bottom & 0x3ff); | ||
2152 | } | ||
2153 | |||
1899 | ret = coda_alloc_framebuffers(ctx, q_data_dst, src_fourcc); | 2154 | ret = coda_alloc_framebuffers(ctx, q_data_dst, src_fourcc); |
1900 | if (ret < 0) | 2155 | if (ret < 0) |
1901 | return ret; | 2156 | return ret; |
@@ -1918,6 +2173,20 @@ static int coda_start_decoding(struct coda_ctx *ctx) | |||
1918 | CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR); | 2173 | CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR); |
1919 | coda_write(dev, ctx->iram_info.buf_ovl_use, | 2174 | coda_write(dev, ctx->iram_info.buf_ovl_use, |
1920 | CODA7_CMD_SET_FRAME_AXI_OVL_ADDR); | 2175 | CODA7_CMD_SET_FRAME_AXI_OVL_ADDR); |
2176 | if (dev->devtype->product == CODA_960) | ||
2177 | coda_write(dev, ctx->iram_info.buf_btp_use, | ||
2178 | CODA9_CMD_SET_FRAME_AXI_BTP_ADDR); | ||
2179 | } | ||
2180 | |||
2181 | if (dev->devtype->product == CODA_960) { | ||
2182 | coda_write(dev, -1, CODA9_CMD_SET_FRAME_DELAY); | ||
2183 | |||
2184 | coda_write(dev, 0x20262024, CODA9_CMD_SET_FRAME_CACHE_SIZE); | ||
2185 | coda_write(dev, 2 << CODA9_CACHE_PAGEMERGE_OFFSET | | ||
2186 | 32 << CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET | | ||
2187 | 8 << CODA9_CACHE_CB_BUFFER_SIZE_OFFSET | | ||
2188 | 8 << CODA9_CACHE_CR_BUFFER_SIZE_OFFSET, | ||
2189 | CODA9_CMD_SET_FRAME_CACHE_CONFIG); | ||
1921 | } | 2190 | } |
1922 | 2191 | ||
1923 | if (src_fourcc == V4L2_PIX_FMT_H264) { | 2192 | if (src_fourcc == V4L2_PIX_FMT_H264) { |
@@ -1931,8 +2200,16 @@ static int coda_start_decoding(struct coda_ctx *ctx) | |||
1931 | int max_mb_x = 1920 / 16; | 2200 | int max_mb_x = 1920 / 16; |
1932 | int max_mb_y = 1088 / 16; | 2201 | int max_mb_y = 1088 / 16; |
1933 | int max_mb_num = max_mb_x * max_mb_y; | 2202 | int max_mb_num = max_mb_x * max_mb_y; |
2203 | |||
1934 | coda_write(dev, max_mb_num << 16 | max_mb_x << 8 | max_mb_y, | 2204 | coda_write(dev, max_mb_num << 16 | max_mb_x << 8 | max_mb_y, |
1935 | CODA7_CMD_SET_FRAME_MAX_DEC_SIZE); | 2205 | CODA7_CMD_SET_FRAME_MAX_DEC_SIZE); |
2206 | } else if (dev->devtype->product == CODA_960) { | ||
2207 | int max_mb_x = 1920 / 16; | ||
2208 | int max_mb_y = 1088 / 16; | ||
2209 | int max_mb_num = max_mb_x * max_mb_y; | ||
2210 | |||
2211 | coda_write(dev, max_mb_num << 16 | max_mb_x << 8 | max_mb_y, | ||
2212 | CODA9_CMD_SET_FRAME_MAX_DEC_SIZE); | ||
1936 | } | 2213 | } |
1937 | 2214 | ||
1938 | if (coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF)) { | 2215 | if (coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF)) { |
@@ -1948,34 +2225,49 @@ static int coda_encode_header(struct coda_ctx *ctx, struct vb2_buffer *buf, | |||
1948 | int header_code, u8 *header, int *size) | 2225 | int header_code, u8 *header, int *size) |
1949 | { | 2226 | { |
1950 | struct coda_dev *dev = ctx->dev; | 2227 | struct coda_dev *dev = ctx->dev; |
2228 | size_t bufsize; | ||
1951 | int ret; | 2229 | int ret; |
2230 | int i; | ||
2231 | |||
2232 | if (dev->devtype->product == CODA_960) | ||
2233 | memset(vb2_plane_vaddr(buf, 0), 0, 64); | ||
1952 | 2234 | ||
1953 | coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0), | 2235 | coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0), |
1954 | CODA_CMD_ENC_HEADER_BB_START); | 2236 | CODA_CMD_ENC_HEADER_BB_START); |
1955 | coda_write(dev, vb2_plane_size(buf, 0), CODA_CMD_ENC_HEADER_BB_SIZE); | 2237 | bufsize = vb2_plane_size(buf, 0); |
2238 | if (dev->devtype->product == CODA_960) | ||
2239 | bufsize /= 1024; | ||
2240 | coda_write(dev, bufsize, CODA_CMD_ENC_HEADER_BB_SIZE); | ||
1956 | coda_write(dev, header_code, CODA_CMD_ENC_HEADER_CODE); | 2241 | coda_write(dev, header_code, CODA_CMD_ENC_HEADER_CODE); |
1957 | ret = coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER); | 2242 | ret = coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER); |
1958 | if (ret < 0) { | 2243 | if (ret < 0) { |
1959 | v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_ENCODE_HEADER timeout\n"); | 2244 | v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_ENCODE_HEADER timeout\n"); |
1960 | return ret; | 2245 | return ret; |
1961 | } | 2246 | } |
1962 | *size = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx)) - | 2247 | |
1963 | coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); | 2248 | if (dev->devtype->product == CODA_960) { |
2249 | for (i = 63; i > 0; i--) | ||
2250 | if (((char *)vb2_plane_vaddr(buf, 0))[i] != 0) | ||
2251 | break; | ||
2252 | *size = i + 1; | ||
2253 | } else { | ||
2254 | *size = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx)) - | ||
2255 | coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); | ||
2256 | } | ||
1964 | memcpy(header, vb2_plane_vaddr(buf, 0), *size); | 2257 | memcpy(header, vb2_plane_vaddr(buf, 0), *size); |
1965 | 2258 | ||
1966 | return 0; | 2259 | return 0; |
1967 | } | 2260 | } |
1968 | 2261 | ||
2262 | static int coda_start_encoding(struct coda_ctx *ctx); | ||
2263 | |||
1969 | static int coda_start_streaming(struct vb2_queue *q, unsigned int count) | 2264 | static int coda_start_streaming(struct vb2_queue *q, unsigned int count) |
1970 | { | 2265 | { |
1971 | struct coda_ctx *ctx = vb2_get_drv_priv(q); | 2266 | struct coda_ctx *ctx = vb2_get_drv_priv(q); |
1972 | struct v4l2_device *v4l2_dev = &ctx->dev->v4l2_dev; | 2267 | struct v4l2_device *v4l2_dev = &ctx->dev->v4l2_dev; |
1973 | u32 bitstream_buf, bitstream_size; | ||
1974 | struct coda_dev *dev = ctx->dev; | 2268 | struct coda_dev *dev = ctx->dev; |
1975 | struct coda_q_data *q_data_src, *q_data_dst; | 2269 | struct coda_q_data *q_data_src, *q_data_dst; |
1976 | struct vb2_buffer *buf; | ||
1977 | u32 dst_fourcc; | 2270 | u32 dst_fourcc; |
1978 | u32 value; | ||
1979 | int ret = 0; | 2271 | int ret = 0; |
1980 | 2272 | ||
1981 | q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | 2273 | q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); |
@@ -2007,13 +2299,10 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) | |||
2007 | 2299 | ||
2008 | /* Allow decoder device_run with no new buffers queued */ | 2300 | /* Allow decoder device_run with no new buffers queued */ |
2009 | if (ctx->inst_type == CODA_INST_DECODER) | 2301 | if (ctx->inst_type == CODA_INST_DECODER) |
2010 | v4l2_m2m_set_src_buffered(ctx->m2m_ctx, true); | 2302 | v4l2_m2m_set_src_buffered(ctx->fh.m2m_ctx, true); |
2011 | 2303 | ||
2012 | ctx->gopcounter = ctx->params.gop_size - 1; | 2304 | ctx->gopcounter = ctx->params.gop_size - 1; |
2013 | buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); | ||
2014 | bitstream_buf = vb2_dma_contig_plane_dma_addr(buf, 0); | ||
2015 | q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); | 2305 | q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); |
2016 | bitstream_size = q_data_dst->sizeimage; | ||
2017 | dst_fourcc = q_data_dst->fourcc; | 2306 | dst_fourcc = q_data_dst->fourcc; |
2018 | 2307 | ||
2019 | ctx->codec = coda_find_codec(ctx->dev, q_data_src->fourcc, | 2308 | ctx->codec = coda_find_codec(ctx->dev, q_data_src->fourcc, |
@@ -2032,16 +2321,36 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) | |||
2032 | mutex_lock(&dev->coda_mutex); | 2321 | mutex_lock(&dev->coda_mutex); |
2033 | ret = coda_start_decoding(ctx); | 2322 | ret = coda_start_decoding(ctx); |
2034 | mutex_unlock(&dev->coda_mutex); | 2323 | mutex_unlock(&dev->coda_mutex); |
2035 | if (ret == -EAGAIN) { | 2324 | if (ret == -EAGAIN) |
2036 | return 0; | 2325 | return 0; |
2037 | } else if (ret < 0) { | 2326 | else if (ret < 0) |
2038 | return ret; | 2327 | return ret; |
2039 | } else { | 2328 | } else { |
2040 | ctx->initialized = 1; | 2329 | ret = coda_start_encoding(ctx); |
2041 | return 0; | ||
2042 | } | ||
2043 | } | 2330 | } |
2044 | 2331 | ||
2332 | ctx->initialized = 1; | ||
2333 | return ret; | ||
2334 | } | ||
2335 | |||
2336 | static int coda_start_encoding(struct coda_ctx *ctx) | ||
2337 | { | ||
2338 | struct coda_dev *dev = ctx->dev; | ||
2339 | struct v4l2_device *v4l2_dev = &dev->v4l2_dev; | ||
2340 | struct coda_q_data *q_data_src, *q_data_dst; | ||
2341 | u32 bitstream_buf, bitstream_size; | ||
2342 | struct vb2_buffer *buf; | ||
2343 | int gamma, ret, value; | ||
2344 | u32 dst_fourcc; | ||
2345 | |||
2346 | q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | ||
2347 | q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); | ||
2348 | dst_fourcc = q_data_dst->fourcc; | ||
2349 | |||
2350 | buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); | ||
2351 | bitstream_buf = vb2_dma_contig_plane_dma_addr(buf, 0); | ||
2352 | bitstream_size = q_data_dst->sizeimage; | ||
2353 | |||
2045 | if (!coda_is_initialized(dev)) { | 2354 | if (!coda_is_initialized(dev)) { |
2046 | v4l2_err(v4l2_dev, "coda is not initialized.\n"); | 2355 | v4l2_err(v4l2_dev, "coda is not initialized.\n"); |
2047 | return -EFAULT; | 2356 | return -EFAULT; |
@@ -2057,14 +2366,23 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) | |||
2057 | coda_write(dev, CODADX6_STREAM_BUF_DYNALLOC_EN | | 2366 | coda_write(dev, CODADX6_STREAM_BUF_DYNALLOC_EN | |
2058 | CODADX6_STREAM_BUF_PIC_RESET, CODA_REG_BIT_STREAM_CTRL); | 2367 | CODADX6_STREAM_BUF_PIC_RESET, CODA_REG_BIT_STREAM_CTRL); |
2059 | break; | 2368 | break; |
2060 | default: | 2369 | case CODA_960: |
2370 | coda_write(dev, 0, CODA9_GDI_WPROT_RGN_EN); | ||
2371 | /* fallthrough */ | ||
2372 | case CODA_7541: | ||
2061 | coda_write(dev, CODA7_STREAM_BUF_DYNALLOC_EN | | 2373 | coda_write(dev, CODA7_STREAM_BUF_DYNALLOC_EN | |
2062 | CODA7_STREAM_BUF_PIC_RESET, CODA_REG_BIT_STREAM_CTRL); | 2374 | CODA7_STREAM_BUF_PIC_RESET, CODA_REG_BIT_STREAM_CTRL); |
2375 | break; | ||
2063 | } | 2376 | } |
2064 | 2377 | ||
2378 | value = coda_read(dev, CODA_REG_BIT_FRAME_MEM_CTRL); | ||
2379 | value &= ~(1 << 2 | 0x7 << 9); | ||
2380 | ctx->frame_mem_ctrl = value; | ||
2381 | coda_write(dev, value, CODA_REG_BIT_FRAME_MEM_CTRL); | ||
2382 | |||
2065 | if (dev->devtype->product == CODA_DX6) { | 2383 | if (dev->devtype->product == CODA_DX6) { |
2066 | /* Configure the coda */ | 2384 | /* Configure the coda */ |
2067 | coda_write(dev, dev->iram_paddr, CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR); | 2385 | coda_write(dev, dev->iram.paddr, CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR); |
2068 | } | 2386 | } |
2069 | 2387 | ||
2070 | /* Could set rotation here if needed */ | 2388 | /* Could set rotation here if needed */ |
@@ -2073,7 +2391,16 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) | |||
2073 | value = (q_data_src->width & CODADX6_PICWIDTH_MASK) << CODADX6_PICWIDTH_OFFSET; | 2391 | value = (q_data_src->width & CODADX6_PICWIDTH_MASK) << CODADX6_PICWIDTH_OFFSET; |
2074 | value |= (q_data_src->height & CODADX6_PICHEIGHT_MASK) << CODA_PICHEIGHT_OFFSET; | 2392 | value |= (q_data_src->height & CODADX6_PICHEIGHT_MASK) << CODA_PICHEIGHT_OFFSET; |
2075 | break; | 2393 | break; |
2076 | default: | 2394 | case CODA_7541: |
2395 | if (dst_fourcc == V4L2_PIX_FMT_H264) { | ||
2396 | value = (round_up(q_data_src->width, 16) & | ||
2397 | CODA7_PICWIDTH_MASK) << CODA7_PICWIDTH_OFFSET; | ||
2398 | value |= (round_up(q_data_src->height, 16) & | ||
2399 | CODA7_PICHEIGHT_MASK) << CODA_PICHEIGHT_OFFSET; | ||
2400 | break; | ||
2401 | } | ||
2402 | /* fallthrough */ | ||
2403 | case CODA_960: | ||
2077 | value = (q_data_src->width & CODA7_PICWIDTH_MASK) << CODA7_PICWIDTH_OFFSET; | 2404 | value = (q_data_src->width & CODA7_PICWIDTH_MASK) << CODA7_PICWIDTH_OFFSET; |
2078 | value |= (q_data_src->height & CODA7_PICHEIGHT_MASK) << CODA_PICHEIGHT_OFFSET; | 2405 | value |= (q_data_src->height & CODA7_PICHEIGHT_MASK) << CODA_PICHEIGHT_OFFSET; |
2079 | } | 2406 | } |
@@ -2084,12 +2411,28 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) | |||
2084 | ctx->params.codec_mode = ctx->codec->mode; | 2411 | ctx->params.codec_mode = ctx->codec->mode; |
2085 | switch (dst_fourcc) { | 2412 | switch (dst_fourcc) { |
2086 | case V4L2_PIX_FMT_MPEG4: | 2413 | case V4L2_PIX_FMT_MPEG4: |
2087 | coda_write(dev, CODA_STD_MPEG4, CODA_CMD_ENC_SEQ_COD_STD); | 2414 | if (dev->devtype->product == CODA_960) |
2415 | coda_write(dev, CODA9_STD_MPEG4, CODA_CMD_ENC_SEQ_COD_STD); | ||
2416 | else | ||
2417 | coda_write(dev, CODA_STD_MPEG4, CODA_CMD_ENC_SEQ_COD_STD); | ||
2088 | coda_write(dev, 0, CODA_CMD_ENC_SEQ_MP4_PARA); | 2418 | coda_write(dev, 0, CODA_CMD_ENC_SEQ_MP4_PARA); |
2089 | break; | 2419 | break; |
2090 | case V4L2_PIX_FMT_H264: | 2420 | case V4L2_PIX_FMT_H264: |
2091 | coda_write(dev, CODA_STD_H264, CODA_CMD_ENC_SEQ_COD_STD); | 2421 | if (dev->devtype->product == CODA_960) |
2092 | coda_write(dev, 0, CODA_CMD_ENC_SEQ_264_PARA); | 2422 | coda_write(dev, CODA9_STD_H264, CODA_CMD_ENC_SEQ_COD_STD); |
2423 | else | ||
2424 | coda_write(dev, CODA_STD_H264, CODA_CMD_ENC_SEQ_COD_STD); | ||
2425 | if (ctx->params.h264_deblk_enabled) { | ||
2426 | value = ((ctx->params.h264_deblk_alpha & | ||
2427 | CODA_264PARAM_DEBLKFILTEROFFSETALPHA_MASK) << | ||
2428 | CODA_264PARAM_DEBLKFILTEROFFSETALPHA_OFFSET) | | ||
2429 | ((ctx->params.h264_deblk_beta & | ||
2430 | CODA_264PARAM_DEBLKFILTEROFFSETBETA_MASK) << | ||
2431 | CODA_264PARAM_DEBLKFILTEROFFSETBETA_OFFSET); | ||
2432 | } else { | ||
2433 | value = 1 << CODA_264PARAM_DISABLEDEBLK_OFFSET; | ||
2434 | } | ||
2435 | coda_write(dev, value, CODA_CMD_ENC_SEQ_264_PARA); | ||
2093 | break; | 2436 | break; |
2094 | default: | 2437 | default: |
2095 | v4l2_err(v4l2_dev, | 2438 | v4l2_err(v4l2_dev, |
@@ -2121,42 +2464,75 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) | |||
2121 | /* Rate control enabled */ | 2464 | /* Rate control enabled */ |
2122 | value = (ctx->params.bitrate & CODA_RATECONTROL_BITRATE_MASK) << CODA_RATECONTROL_BITRATE_OFFSET; | 2465 | value = (ctx->params.bitrate & CODA_RATECONTROL_BITRATE_MASK) << CODA_RATECONTROL_BITRATE_OFFSET; |
2123 | value |= 1 & CODA_RATECONTROL_ENABLE_MASK; | 2466 | value |= 1 & CODA_RATECONTROL_ENABLE_MASK; |
2467 | if (dev->devtype->product == CODA_960) | ||
2468 | value |= BIT(31); /* disable autoskip */ | ||
2124 | } else { | 2469 | } else { |
2125 | value = 0; | 2470 | value = 0; |
2126 | } | 2471 | } |
2127 | coda_write(dev, value, CODA_CMD_ENC_SEQ_RC_PARA); | 2472 | coda_write(dev, value, CODA_CMD_ENC_SEQ_RC_PARA); |
2128 | 2473 | ||
2129 | coda_write(dev, 0, CODA_CMD_ENC_SEQ_RC_BUF_SIZE); | 2474 | coda_write(dev, 0, CODA_CMD_ENC_SEQ_RC_BUF_SIZE); |
2130 | coda_write(dev, 0, CODA_CMD_ENC_SEQ_INTRA_REFRESH); | 2475 | coda_write(dev, ctx->params.intra_refresh, |
2476 | CODA_CMD_ENC_SEQ_INTRA_REFRESH); | ||
2131 | 2477 | ||
2132 | coda_write(dev, bitstream_buf, CODA_CMD_ENC_SEQ_BB_START); | 2478 | coda_write(dev, bitstream_buf, CODA_CMD_ENC_SEQ_BB_START); |
2133 | coda_write(dev, bitstream_size / 1024, CODA_CMD_ENC_SEQ_BB_SIZE); | 2479 | coda_write(dev, bitstream_size / 1024, CODA_CMD_ENC_SEQ_BB_SIZE); |
2134 | 2480 | ||
2135 | /* set default gamma */ | ||
2136 | value = (CODA_DEFAULT_GAMMA & CODA_GAMMA_MASK) << CODA_GAMMA_OFFSET; | ||
2137 | coda_write(dev, value, CODA_CMD_ENC_SEQ_RC_GAMMA); | ||
2138 | 2481 | ||
2139 | if (CODA_DEFAULT_GAMMA > 0) { | 2482 | value = 0; |
2140 | if (dev->devtype->product == CODA_DX6) | 2483 | if (dev->devtype->product == CODA_960) |
2141 | value = 1 << CODADX6_OPTION_GAMMA_OFFSET; | 2484 | gamma = CODA9_DEFAULT_GAMMA; |
2142 | else | 2485 | else |
2143 | value = 1 << CODA7_OPTION_GAMMA_OFFSET; | 2486 | gamma = CODA_DEFAULT_GAMMA; |
2487 | if (gamma > 0) { | ||
2488 | coda_write(dev, (gamma & CODA_GAMMA_MASK) << CODA_GAMMA_OFFSET, | ||
2489 | CODA_CMD_ENC_SEQ_RC_GAMMA); | ||
2490 | } | ||
2491 | |||
2492 | if (ctx->params.h264_min_qp || ctx->params.h264_max_qp) { | ||
2493 | coda_write(dev, | ||
2494 | ctx->params.h264_min_qp << CODA_QPMIN_OFFSET | | ||
2495 | ctx->params.h264_max_qp << CODA_QPMAX_OFFSET, | ||
2496 | CODA_CMD_ENC_SEQ_RC_QP_MIN_MAX); | ||
2497 | } | ||
2498 | if (dev->devtype->product == CODA_960) { | ||
2499 | if (ctx->params.h264_max_qp) | ||
2500 | value |= 1 << CODA9_OPTION_RCQPMAX_OFFSET; | ||
2501 | if (CODA_DEFAULT_GAMMA > 0) | ||
2502 | value |= 1 << CODA9_OPTION_GAMMA_OFFSET; | ||
2144 | } else { | 2503 | } else { |
2145 | value = 0; | 2504 | if (CODA_DEFAULT_GAMMA > 0) { |
2505 | if (dev->devtype->product == CODA_DX6) | ||
2506 | value |= 1 << CODADX6_OPTION_GAMMA_OFFSET; | ||
2507 | else | ||
2508 | value |= 1 << CODA7_OPTION_GAMMA_OFFSET; | ||
2509 | } | ||
2510 | if (ctx->params.h264_min_qp) | ||
2511 | value |= 1 << CODA7_OPTION_RCQPMIN_OFFSET; | ||
2512 | if (ctx->params.h264_max_qp) | ||
2513 | value |= 1 << CODA7_OPTION_RCQPMAX_OFFSET; | ||
2146 | } | 2514 | } |
2147 | coda_write(dev, value, CODA_CMD_ENC_SEQ_OPTION); | 2515 | coda_write(dev, value, CODA_CMD_ENC_SEQ_OPTION); |
2148 | 2516 | ||
2517 | coda_write(dev, 0, CODA_CMD_ENC_SEQ_RC_INTERVAL_MODE); | ||
2518 | |||
2149 | coda_setup_iram(ctx); | 2519 | coda_setup_iram(ctx); |
2150 | 2520 | ||
2151 | if (dst_fourcc == V4L2_PIX_FMT_H264) { | 2521 | if (dst_fourcc == V4L2_PIX_FMT_H264) { |
2152 | if (dev->devtype->product == CODA_DX6) { | 2522 | switch (dev->devtype->product) { |
2523 | case CODA_DX6: | ||
2153 | value = FMO_SLICE_SAVE_BUF_SIZE << 7; | 2524 | value = FMO_SLICE_SAVE_BUF_SIZE << 7; |
2154 | coda_write(dev, value, CODADX6_CMD_ENC_SEQ_FMO); | 2525 | coda_write(dev, value, CODADX6_CMD_ENC_SEQ_FMO); |
2155 | } else { | 2526 | break; |
2527 | case CODA_7541: | ||
2156 | coda_write(dev, ctx->iram_info.search_ram_paddr, | 2528 | coda_write(dev, ctx->iram_info.search_ram_paddr, |
2157 | CODA7_CMD_ENC_SEQ_SEARCH_BASE); | 2529 | CODA7_CMD_ENC_SEQ_SEARCH_BASE); |
2158 | coda_write(dev, ctx->iram_info.search_ram_size, | 2530 | coda_write(dev, ctx->iram_info.search_ram_size, |
2159 | CODA7_CMD_ENC_SEQ_SEARCH_SIZE); | 2531 | CODA7_CMD_ENC_SEQ_SEARCH_SIZE); |
2532 | break; | ||
2533 | case CODA_960: | ||
2534 | coda_write(dev, 0, CODA9_CMD_ENC_SEQ_ME_OPTION); | ||
2535 | coda_write(dev, 0, CODA9_CMD_ENC_SEQ_INTRA_WEIGHT); | ||
2160 | } | 2536 | } |
2161 | } | 2537 | } |
2162 | 2538 | ||
@@ -2172,7 +2548,10 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) | |||
2172 | goto out; | 2548 | goto out; |
2173 | } | 2549 | } |
2174 | 2550 | ||
2175 | ctx->num_internal_frames = 2; | 2551 | if (dev->devtype->product == CODA_960) |
2552 | ctx->num_internal_frames = 4; | ||
2553 | else | ||
2554 | ctx->num_internal_frames = 2; | ||
2176 | ret = coda_alloc_framebuffers(ctx, q_data_src, dst_fourcc); | 2555 | ret = coda_alloc_framebuffers(ctx, q_data_src, dst_fourcc); |
2177 | if (ret < 0) { | 2556 | if (ret < 0) { |
2178 | v4l2_err(v4l2_dev, "failed to allocate framebuffers\n"); | 2557 | v4l2_err(v4l2_dev, "failed to allocate framebuffers\n"); |
@@ -2180,10 +2559,12 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) | |||
2180 | } | 2559 | } |
2181 | 2560 | ||
2182 | coda_write(dev, ctx->num_internal_frames, CODA_CMD_SET_FRAME_BUF_NUM); | 2561 | coda_write(dev, ctx->num_internal_frames, CODA_CMD_SET_FRAME_BUF_NUM); |
2183 | coda_write(dev, round_up(q_data_src->width, 8), CODA_CMD_SET_FRAME_BUF_STRIDE); | 2562 | coda_write(dev, q_data_src->bytesperline, |
2184 | if (dev->devtype->product == CODA_7541) | 2563 | CODA_CMD_SET_FRAME_BUF_STRIDE); |
2185 | coda_write(dev, round_up(q_data_src->width, 8), | 2564 | if (dev->devtype->product == CODA_7541) { |
2565 | coda_write(dev, q_data_src->bytesperline, | ||
2186 | CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE); | 2566 | CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE); |
2567 | } | ||
2187 | if (dev->devtype->product != CODA_DX6) { | 2568 | if (dev->devtype->product != CODA_DX6) { |
2188 | coda_write(dev, ctx->iram_info.buf_bit_use, | 2569 | coda_write(dev, ctx->iram_info.buf_bit_use, |
2189 | CODA7_CMD_SET_FRAME_AXI_BIT_ADDR); | 2570 | CODA7_CMD_SET_FRAME_AXI_BIT_ADDR); |
@@ -2195,7 +2576,16 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) | |||
2195 | CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR); | 2576 | CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR); |
2196 | coda_write(dev, ctx->iram_info.buf_ovl_use, | 2577 | coda_write(dev, ctx->iram_info.buf_ovl_use, |
2197 | CODA7_CMD_SET_FRAME_AXI_OVL_ADDR); | 2578 | CODA7_CMD_SET_FRAME_AXI_OVL_ADDR); |
2579 | if (dev->devtype->product == CODA_960) { | ||
2580 | coda_write(dev, ctx->iram_info.buf_btp_use, | ||
2581 | CODA9_CMD_SET_FRAME_AXI_BTP_ADDR); | ||
2582 | |||
2583 | /* FIXME */ | ||
2584 | coda_write(dev, ctx->internal_frames[2].paddr, CODA9_CMD_SET_FRAME_SUBSAMP_A); | ||
2585 | coda_write(dev, ctx->internal_frames[3].paddr, CODA9_CMD_SET_FRAME_SUBSAMP_B); | ||
2586 | } | ||
2198 | } | 2587 | } |
2588 | |||
2199 | ret = coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF); | 2589 | ret = coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF); |
2200 | if (ret < 0) { | 2590 | if (ret < 0) { |
2201 | v4l2_err(v4l2_dev, "CODA_COMMAND_SET_FRAME_BUF timeout\n"); | 2591 | v4l2_err(v4l2_dev, "CODA_COMMAND_SET_FRAME_BUF timeout\n"); |
@@ -2203,7 +2593,7 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) | |||
2203 | } | 2593 | } |
2204 | 2594 | ||
2205 | /* Save stream headers */ | 2595 | /* Save stream headers */ |
2206 | buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); | 2596 | buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); |
2207 | switch (dst_fourcc) { | 2597 | switch (dst_fourcc) { |
2208 | case V4L2_PIX_FMT_H264: | 2598 | case V4L2_PIX_FMT_H264: |
2209 | /* | 2599 | /* |
@@ -2279,6 +2669,17 @@ static void coda_stop_streaming(struct vb2_queue *q) | |||
2279 | "%s: output\n", __func__); | 2669 | "%s: output\n", __func__); |
2280 | ctx->streamon_out = 0; | 2670 | ctx->streamon_out = 0; |
2281 | 2671 | ||
2672 | if (ctx->inst_type == CODA_INST_DECODER && | ||
2673 | coda_isbusy(dev) && ctx->idx == coda_read(dev, CODA_REG_BIT_RUN_INDEX)) { | ||
2674 | /* if this decoder instance is running, set the stream end flag */ | ||
2675 | if (dev->devtype->product == CODA_960) { | ||
2676 | u32 val = coda_read(dev, CODA_REG_BIT_BIT_STREAM_PARAM); | ||
2677 | |||
2678 | val |= CODA_BIT_STREAM_END_FLAG; | ||
2679 | coda_write(dev, val, CODA_REG_BIT_BIT_STREAM_PARAM); | ||
2680 | ctx->bit_stream_param = val; | ||
2681 | } | ||
2682 | } | ||
2282 | ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG; | 2683 | ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG; |
2283 | 2684 | ||
2284 | ctx->isequence = 0; | 2685 | ctx->isequence = 0; |
@@ -2288,9 +2689,18 @@ static void coda_stop_streaming(struct vb2_queue *q) | |||
2288 | ctx->streamon_cap = 0; | 2689 | ctx->streamon_cap = 0; |
2289 | 2690 | ||
2290 | ctx->osequence = 0; | 2691 | ctx->osequence = 0; |
2692 | ctx->sequence_offset = 0; | ||
2291 | } | 2693 | } |
2292 | 2694 | ||
2293 | if (!ctx->streamon_out && !ctx->streamon_cap) { | 2695 | if (!ctx->streamon_out && !ctx->streamon_cap) { |
2696 | struct coda_timestamp *ts; | ||
2697 | |||
2698 | while (!list_empty(&ctx->timestamp_list)) { | ||
2699 | ts = list_first_entry(&ctx->timestamp_list, | ||
2700 | struct coda_timestamp, list); | ||
2701 | list_del(&ts->list); | ||
2702 | kfree(ts); | ||
2703 | } | ||
2294 | kfifo_init(&ctx->bitstream_fifo, | 2704 | kfifo_init(&ctx->bitstream_fifo, |
2295 | ctx->bitstream.vaddr, ctx->bitstream.size); | 2705 | ctx->bitstream.vaddr, ctx->bitstream.size); |
2296 | ctx->runcounter = 0; | 2706 | ctx->runcounter = 0; |
@@ -2301,10 +2711,10 @@ static struct vb2_ops coda_qops = { | |||
2301 | .queue_setup = coda_queue_setup, | 2711 | .queue_setup = coda_queue_setup, |
2302 | .buf_prepare = coda_buf_prepare, | 2712 | .buf_prepare = coda_buf_prepare, |
2303 | .buf_queue = coda_buf_queue, | 2713 | .buf_queue = coda_buf_queue, |
2304 | .wait_prepare = coda_wait_prepare, | ||
2305 | .wait_finish = coda_wait_finish, | ||
2306 | .start_streaming = coda_start_streaming, | 2714 | .start_streaming = coda_start_streaming, |
2307 | .stop_streaming = coda_stop_streaming, | 2715 | .stop_streaming = coda_stop_streaming, |
2716 | .wait_prepare = vb2_ops_wait_prepare, | ||
2717 | .wait_finish = vb2_ops_wait_finish, | ||
2308 | }; | 2718 | }; |
2309 | 2719 | ||
2310 | static int coda_s_ctrl(struct v4l2_ctrl *ctrl) | 2720 | static int coda_s_ctrl(struct v4l2_ctrl *ctrl) |
@@ -2340,6 +2750,22 @@ static int coda_s_ctrl(struct v4l2_ctrl *ctrl) | |||
2340 | case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP: | 2750 | case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP: |
2341 | ctx->params.h264_inter_qp = ctrl->val; | 2751 | ctx->params.h264_inter_qp = ctrl->val; |
2342 | break; | 2752 | break; |
2753 | case V4L2_CID_MPEG_VIDEO_H264_MIN_QP: | ||
2754 | ctx->params.h264_min_qp = ctrl->val; | ||
2755 | break; | ||
2756 | case V4L2_CID_MPEG_VIDEO_H264_MAX_QP: | ||
2757 | ctx->params.h264_max_qp = ctrl->val; | ||
2758 | break; | ||
2759 | case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA: | ||
2760 | ctx->params.h264_deblk_alpha = ctrl->val; | ||
2761 | break; | ||
2762 | case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA: | ||
2763 | ctx->params.h264_deblk_beta = ctrl->val; | ||
2764 | break; | ||
2765 | case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE: | ||
2766 | ctx->params.h264_deblk_enabled = (ctrl->val == | ||
2767 | V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED); | ||
2768 | break; | ||
2343 | case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP: | 2769 | case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP: |
2344 | ctx->params.mpeg4_intra_qp = ctrl->val; | 2770 | ctx->params.mpeg4_intra_qp = ctrl->val; |
2345 | break; | 2771 | break; |
@@ -2357,6 +2783,9 @@ static int coda_s_ctrl(struct v4l2_ctrl *ctrl) | |||
2357 | break; | 2783 | break; |
2358 | case V4L2_CID_MPEG_VIDEO_HEADER_MODE: | 2784 | case V4L2_CID_MPEG_VIDEO_HEADER_MODE: |
2359 | break; | 2785 | break; |
2786 | case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB: | ||
2787 | ctx->params.intra_refresh = ctrl->val; | ||
2788 | break; | ||
2360 | default: | 2789 | default: |
2361 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, | 2790 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, |
2362 | "Invalid control, id=%d, val=%d\n", | 2791 | "Invalid control, id=%d, val=%d\n", |
@@ -2384,9 +2813,23 @@ static int coda_ctrls_setup(struct coda_ctx *ctx) | |||
2384 | v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, | 2813 | v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, |
2385 | V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 60, 1, 16); | 2814 | V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 60, 1, 16); |
2386 | v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, | 2815 | v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, |
2387 | V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP, 1, 51, 1, 25); | 2816 | V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP, 0, 51, 1, 25); |
2817 | v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, | ||
2818 | V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP, 0, 51, 1, 25); | ||
2819 | if (ctx->dev->devtype->product != CODA_960) { | ||
2820 | v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, | ||
2821 | V4L2_CID_MPEG_VIDEO_H264_MIN_QP, 0, 51, 1, 12); | ||
2822 | } | ||
2823 | v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, | ||
2824 | V4L2_CID_MPEG_VIDEO_H264_MAX_QP, 0, 51, 1, 51); | ||
2388 | v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, | 2825 | v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, |
2389 | V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP, 1, 51, 1, 25); | 2826 | V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA, 0, 15, 1, 0); |
2827 | v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, | ||
2828 | V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA, 0, 15, 1, 0); | ||
2829 | v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops, | ||
2830 | V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE, | ||
2831 | V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED, 0x0, | ||
2832 | V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED); | ||
2390 | v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, | 2833 | v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, |
2391 | V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP, 1, 31, 1, 2); | 2834 | V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP, 1, 31, 1, 2); |
2392 | v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, | 2835 | v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, |
@@ -2404,6 +2847,8 @@ static int coda_ctrls_setup(struct coda_ctx *ctx) | |||
2404 | V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, | 2847 | V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, |
2405 | (1 << V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE), | 2848 | (1 << V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE), |
2406 | V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME); | 2849 | V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME); |
2850 | v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, | ||
2851 | V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB, 0, 1920 * 1088 / 256, 1, 0); | ||
2407 | 2852 | ||
2408 | if (ctx->ctrls.error) { | 2853 | if (ctx->ctrls.error) { |
2409 | v4l2_err(&ctx->dev->v4l2_dev, "control initialization error (%d)", | 2854 | v4l2_err(&ctx->dev->v4l2_dev, "control initialization error (%d)", |
@@ -2427,6 +2872,7 @@ static int coda_queue_init(void *priv, struct vb2_queue *src_vq, | |||
2427 | src_vq->ops = &coda_qops; | 2872 | src_vq->ops = &coda_qops; |
2428 | src_vq->mem_ops = &vb2_dma_contig_memops; | 2873 | src_vq->mem_ops = &vb2_dma_contig_memops; |
2429 | src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; | 2874 | src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; |
2875 | src_vq->lock = &ctx->dev->dev_mutex; | ||
2430 | 2876 | ||
2431 | ret = vb2_queue_init(src_vq); | 2877 | ret = vb2_queue_init(src_vq); |
2432 | if (ret) | 2878 | if (ret) |
@@ -2439,6 +2885,7 @@ static int coda_queue_init(void *priv, struct vb2_queue *src_vq, | |||
2439 | dst_vq->ops = &coda_qops; | 2885 | dst_vq->ops = &coda_qops; |
2440 | dst_vq->mem_ops = &vb2_dma_contig_memops; | 2886 | dst_vq->mem_ops = &vb2_dma_contig_memops; |
2441 | dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; | 2887 | dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; |
2888 | dst_vq->lock = &ctx->dev->dev_mutex; | ||
2442 | 2889 | ||
2443 | return vb2_queue_init(dst_vq); | 2890 | return vb2_queue_init(dst_vq); |
2444 | } | 2891 | } |
@@ -2458,6 +2905,7 @@ static int coda_open(struct file *file) | |||
2458 | { | 2905 | { |
2459 | struct coda_dev *dev = video_drvdata(file); | 2906 | struct coda_dev *dev = video_drvdata(file); |
2460 | struct coda_ctx *ctx = NULL; | 2907 | struct coda_ctx *ctx = NULL; |
2908 | char *name; | ||
2461 | int ret; | 2909 | int ret; |
2462 | int idx; | 2910 | int idx; |
2463 | 2911 | ||
@@ -2472,7 +2920,13 @@ static int coda_open(struct file *file) | |||
2472 | } | 2920 | } |
2473 | set_bit(idx, &dev->instance_mask); | 2921 | set_bit(idx, &dev->instance_mask); |
2474 | 2922 | ||
2475 | INIT_WORK(&ctx->skip_run, coda_skip_run); | 2923 | name = kasprintf(GFP_KERNEL, "context%d", idx); |
2924 | ctx->debugfs_entry = debugfs_create_dir(name, dev->debugfs_root); | ||
2925 | kfree(name); | ||
2926 | |||
2927 | init_completion(&ctx->completion); | ||
2928 | INIT_WORK(&ctx->pic_run_work, coda_pic_run_work); | ||
2929 | INIT_WORK(&ctx->seq_end_work, coda_seq_end_work); | ||
2476 | v4l2_fh_init(&ctx->fh, video_devdata(file)); | 2930 | v4l2_fh_init(&ctx->fh, video_devdata(file)); |
2477 | file->private_data = &ctx->fh; | 2931 | file->private_data = &ctx->fh; |
2478 | v4l2_fh_add(&ctx->fh); | 2932 | v4l2_fh_add(&ctx->fh); |
@@ -2480,12 +2934,20 @@ static int coda_open(struct file *file) | |||
2480 | ctx->idx = idx; | 2934 | ctx->idx = idx; |
2481 | switch (dev->devtype->product) { | 2935 | switch (dev->devtype->product) { |
2482 | case CODA_7541: | 2936 | case CODA_7541: |
2937 | case CODA_960: | ||
2483 | ctx->reg_idx = 0; | 2938 | ctx->reg_idx = 0; |
2484 | break; | 2939 | break; |
2485 | default: | 2940 | default: |
2486 | ctx->reg_idx = idx; | 2941 | ctx->reg_idx = idx; |
2487 | } | 2942 | } |
2488 | 2943 | ||
2944 | /* Power up and upload firmware if necessary */ | ||
2945 | ret = pm_runtime_get_sync(&dev->plat_dev->dev); | ||
2946 | if (ret < 0) { | ||
2947 | v4l2_err(&dev->v4l2_dev, "failed to power up: %d\n", ret); | ||
2948 | goto err_pm_get; | ||
2949 | } | ||
2950 | |||
2489 | ret = clk_prepare_enable(dev->clk_per); | 2951 | ret = clk_prepare_enable(dev->clk_per); |
2490 | if (ret) | 2952 | if (ret) |
2491 | goto err_clk_per; | 2953 | goto err_clk_per; |
@@ -2495,15 +2957,16 @@ static int coda_open(struct file *file) | |||
2495 | goto err_clk_ahb; | 2957 | goto err_clk_ahb; |
2496 | 2958 | ||
2497 | set_default_params(ctx); | 2959 | set_default_params(ctx); |
2498 | ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, | 2960 | ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, |
2499 | &coda_queue_init); | 2961 | &coda_queue_init); |
2500 | if (IS_ERR(ctx->m2m_ctx)) { | 2962 | if (IS_ERR(ctx->fh.m2m_ctx)) { |
2501 | ret = PTR_ERR(ctx->m2m_ctx); | 2963 | ret = PTR_ERR(ctx->fh.m2m_ctx); |
2502 | 2964 | ||
2503 | v4l2_err(&dev->v4l2_dev, "%s return error (%d)\n", | 2965 | v4l2_err(&dev->v4l2_dev, "%s return error (%d)\n", |
2504 | __func__, ret); | 2966 | __func__, ret); |
2505 | goto err_ctx_init; | 2967 | goto err_ctx_init; |
2506 | } | 2968 | } |
2969 | |||
2507 | ret = coda_ctrls_setup(ctx); | 2970 | ret = coda_ctrls_setup(ctx); |
2508 | if (ret) { | 2971 | if (ret) { |
2509 | v4l2_err(&dev->v4l2_dev, "failed to setup coda controls\n"); | 2972 | v4l2_err(&dev->v4l2_dev, "failed to setup coda controls\n"); |
@@ -2512,7 +2975,8 @@ static int coda_open(struct file *file) | |||
2512 | 2975 | ||
2513 | ctx->fh.ctrl_handler = &ctx->ctrls; | 2976 | ctx->fh.ctrl_handler = &ctx->ctrls; |
2514 | 2977 | ||
2515 | ret = coda_alloc_context_buf(ctx, &ctx->parabuf, CODA_PARA_BUF_SIZE); | 2978 | ret = coda_alloc_context_buf(ctx, &ctx->parabuf, CODA_PARA_BUF_SIZE, |
2979 | "parabuf"); | ||
2516 | if (ret < 0) { | 2980 | if (ret < 0) { |
2517 | v4l2_err(&dev->v4l2_dev, "failed to allocate parabuf"); | 2981 | v4l2_err(&dev->v4l2_dev, "failed to allocate parabuf"); |
2518 | goto err_dma_alloc; | 2982 | goto err_dma_alloc; |
@@ -2530,6 +2994,7 @@ static int coda_open(struct file *file) | |||
2530 | ctx->bitstream.vaddr, ctx->bitstream.size); | 2994 | ctx->bitstream.vaddr, ctx->bitstream.size); |
2531 | mutex_init(&ctx->bitstream_mutex); | 2995 | mutex_init(&ctx->bitstream_mutex); |
2532 | mutex_init(&ctx->buffer_mutex); | 2996 | mutex_init(&ctx->buffer_mutex); |
2997 | INIT_LIST_HEAD(&ctx->timestamp_list); | ||
2533 | 2998 | ||
2534 | coda_lock(ctx); | 2999 | coda_lock(ctx); |
2535 | list_add(&ctx->list, &dev->instances); | 3000 | list_add(&ctx->list, &dev->instances); |
@@ -2548,12 +3013,14 @@ err_dma_writecombine: | |||
2548 | err_dma_alloc: | 3013 | err_dma_alloc: |
2549 | v4l2_ctrl_handler_free(&ctx->ctrls); | 3014 | v4l2_ctrl_handler_free(&ctx->ctrls); |
2550 | err_ctrls_setup: | 3015 | err_ctrls_setup: |
2551 | v4l2_m2m_ctx_release(ctx->m2m_ctx); | 3016 | v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); |
2552 | err_ctx_init: | 3017 | err_ctx_init: |
2553 | clk_disable_unprepare(dev->clk_ahb); | 3018 | clk_disable_unprepare(dev->clk_ahb); |
2554 | err_clk_ahb: | 3019 | err_clk_ahb: |
2555 | clk_disable_unprepare(dev->clk_per); | 3020 | clk_disable_unprepare(dev->clk_per); |
2556 | err_clk_per: | 3021 | err_clk_per: |
3022 | pm_runtime_put_sync(&dev->plat_dev->dev); | ||
3023 | err_pm_get: | ||
2557 | v4l2_fh_del(&ctx->fh); | 3024 | v4l2_fh_del(&ctx->fh); |
2558 | v4l2_fh_exit(&ctx->fh); | 3025 | v4l2_fh_exit(&ctx->fh); |
2559 | clear_bit(ctx->idx, &dev->instance_mask); | 3026 | clear_bit(ctx->idx, &dev->instance_mask); |
@@ -2570,20 +3037,16 @@ static int coda_release(struct file *file) | |||
2570 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "Releasing instance %p\n", | 3037 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "Releasing instance %p\n", |
2571 | ctx); | 3038 | ctx); |
2572 | 3039 | ||
3040 | debugfs_remove_recursive(ctx->debugfs_entry); | ||
3041 | |||
2573 | /* If this instance is running, call .job_abort and wait for it to end */ | 3042 | /* If this instance is running, call .job_abort and wait for it to end */ |
2574 | v4l2_m2m_ctx_release(ctx->m2m_ctx); | 3043 | v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); |
2575 | 3044 | ||
2576 | /* In case the instance was not running, we still need to call SEQ_END */ | 3045 | /* In case the instance was not running, we still need to call SEQ_END */ |
2577 | mutex_lock(&dev->coda_mutex); | 3046 | if (ctx->initialized) { |
2578 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, | 3047 | queue_work(dev->workqueue, &ctx->seq_end_work); |
2579 | "%s: sent command 'SEQ_END' to coda\n", __func__); | 3048 | flush_work(&ctx->seq_end_work); |
2580 | if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) { | ||
2581 | v4l2_err(&dev->v4l2_dev, | ||
2582 | "CODA_COMMAND_SEQ_END failed\n"); | ||
2583 | mutex_unlock(&dev->coda_mutex); | ||
2584 | return -ETIMEDOUT; | ||
2585 | } | 3049 | } |
2586 | mutex_unlock(&dev->coda_mutex); | ||
2587 | 3050 | ||
2588 | coda_free_framebuffers(ctx); | 3051 | coda_free_framebuffers(ctx); |
2589 | 3052 | ||
@@ -2601,6 +3064,7 @@ static int coda_release(struct file *file) | |||
2601 | v4l2_ctrl_handler_free(&ctx->ctrls); | 3064 | v4l2_ctrl_handler_free(&ctx->ctrls); |
2602 | clk_disable_unprepare(dev->clk_ahb); | 3065 | clk_disable_unprepare(dev->clk_ahb); |
2603 | clk_disable_unprepare(dev->clk_per); | 3066 | clk_disable_unprepare(dev->clk_per); |
3067 | pm_runtime_put_sync(&dev->plat_dev->dev); | ||
2604 | v4l2_fh_del(&ctx->fh); | 3068 | v4l2_fh_del(&ctx->fh); |
2605 | v4l2_fh_exit(&ctx->fh); | 3069 | v4l2_fh_exit(&ctx->fh); |
2606 | clear_bit(ctx->idx, &dev->instance_mask); | 3070 | clear_bit(ctx->idx, &dev->instance_mask); |
@@ -2609,32 +3073,13 @@ static int coda_release(struct file *file) | |||
2609 | return 0; | 3073 | return 0; |
2610 | } | 3074 | } |
2611 | 3075 | ||
2612 | static unsigned int coda_poll(struct file *file, | ||
2613 | struct poll_table_struct *wait) | ||
2614 | { | ||
2615 | struct coda_ctx *ctx = fh_to_ctx(file->private_data); | ||
2616 | int ret; | ||
2617 | |||
2618 | coda_lock(ctx); | ||
2619 | ret = v4l2_m2m_poll(file, ctx->m2m_ctx, wait); | ||
2620 | coda_unlock(ctx); | ||
2621 | return ret; | ||
2622 | } | ||
2623 | |||
2624 | static int coda_mmap(struct file *file, struct vm_area_struct *vma) | ||
2625 | { | ||
2626 | struct coda_ctx *ctx = fh_to_ctx(file->private_data); | ||
2627 | |||
2628 | return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); | ||
2629 | } | ||
2630 | |||
2631 | static const struct v4l2_file_operations coda_fops = { | 3076 | static const struct v4l2_file_operations coda_fops = { |
2632 | .owner = THIS_MODULE, | 3077 | .owner = THIS_MODULE, |
2633 | .open = coda_open, | 3078 | .open = coda_open, |
2634 | .release = coda_release, | 3079 | .release = coda_release, |
2635 | .poll = coda_poll, | 3080 | .poll = v4l2_m2m_fop_poll, |
2636 | .unlocked_ioctl = video_ioctl2, | 3081 | .unlocked_ioctl = video_ioctl2, |
2637 | .mmap = coda_mmap, | 3082 | .mmap = v4l2_m2m_fop_mmap, |
2638 | }; | 3083 | }; |
2639 | 3084 | ||
2640 | static void coda_finish_decode(struct coda_ctx *ctx) | 3085 | static void coda_finish_decode(struct coda_ctx *ctx) |
@@ -2643,14 +3088,16 @@ static void coda_finish_decode(struct coda_ctx *ctx) | |||
2643 | struct coda_q_data *q_data_src; | 3088 | struct coda_q_data *q_data_src; |
2644 | struct coda_q_data *q_data_dst; | 3089 | struct coda_q_data *q_data_dst; |
2645 | struct vb2_buffer *dst_buf; | 3090 | struct vb2_buffer *dst_buf; |
3091 | struct coda_timestamp *ts; | ||
2646 | int width, height; | 3092 | int width, height; |
2647 | int decoded_idx; | 3093 | int decoded_idx; |
2648 | int display_idx; | 3094 | int display_idx; |
2649 | u32 src_fourcc; | 3095 | u32 src_fourcc; |
2650 | int success; | 3096 | int success; |
3097 | u32 err_mb; | ||
2651 | u32 val; | 3098 | u32 val; |
2652 | 3099 | ||
2653 | dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); | 3100 | dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); |
2654 | 3101 | ||
2655 | /* Update kfifo out pointer from coda bitstream read pointer */ | 3102 | /* Update kfifo out pointer from coda bitstream read pointer */ |
2656 | coda_kfifo_sync_from_device(ctx); | 3103 | coda_kfifo_sync_from_device(ctx); |
@@ -2693,19 +3140,34 @@ static void coda_finish_decode(struct coda_ctx *ctx) | |||
2693 | 3140 | ||
2694 | q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); | 3141 | q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); |
2695 | 3142 | ||
2696 | val = coda_read(dev, CODA_RET_DEC_PIC_TYPE); | 3143 | /* frame crop information */ |
2697 | if ((val & 0x7) == 0) { | 3144 | if (src_fourcc == V4L2_PIX_FMT_H264) { |
2698 | dst_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME; | 3145 | u32 left_right; |
2699 | dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_PFRAME; | 3146 | u32 top_bottom; |
3147 | |||
3148 | left_right = coda_read(dev, CODA_RET_DEC_PIC_CROP_LEFT_RIGHT); | ||
3149 | top_bottom = coda_read(dev, CODA_RET_DEC_PIC_CROP_TOP_BOTTOM); | ||
3150 | |||
3151 | if (left_right == 0xffffffff && top_bottom == 0xffffffff) { | ||
3152 | /* Keep current crop information */ | ||
3153 | } else { | ||
3154 | struct v4l2_rect *rect = &q_data_dst->rect; | ||
3155 | |||
3156 | rect->left = left_right >> 16 & 0xffff; | ||
3157 | rect->top = top_bottom >> 16 & 0xffff; | ||
3158 | rect->width = width - rect->left - | ||
3159 | (left_right & 0xffff); | ||
3160 | rect->height = height - rect->top - | ||
3161 | (top_bottom & 0xffff); | ||
3162 | } | ||
2700 | } else { | 3163 | } else { |
2701 | dst_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME; | 3164 | /* no cropping */ |
2702 | dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_KEYFRAME; | ||
2703 | } | 3165 | } |
2704 | 3166 | ||
2705 | val = coda_read(dev, CODA_RET_DEC_PIC_ERR_MB); | 3167 | err_mb = coda_read(dev, CODA_RET_DEC_PIC_ERR_MB); |
2706 | if (val > 0) | 3168 | if (err_mb > 0) |
2707 | v4l2_err(&dev->v4l2_dev, | 3169 | v4l2_err(&dev->v4l2_dev, |
2708 | "errors in %d macroblocks\n", val); | 3170 | "errors in %d macroblocks\n", err_mb); |
2709 | 3171 | ||
2710 | if (dev->devtype->product == CODA_7541) { | 3172 | if (dev->devtype->product == CODA_7541) { |
2711 | val = coda_read(dev, CODA_RET_DEC_PIC_OPTION); | 3173 | val = coda_read(dev, CODA_RET_DEC_PIC_OPTION); |
@@ -2713,7 +3175,7 @@ static void coda_finish_decode(struct coda_ctx *ctx) | |||
2713 | /* not enough bitstream data */ | 3175 | /* not enough bitstream data */ |
2714 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, | 3176 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, |
2715 | "prescan failed: %d\n", val); | 3177 | "prescan failed: %d\n", val); |
2716 | ctx->prescan_failed = true; | 3178 | ctx->hold = true; |
2717 | return; | 3179 | return; |
2718 | } | 3180 | } |
2719 | } | 3181 | } |
@@ -2741,13 +3203,38 @@ static void coda_finish_decode(struct coda_ctx *ctx) | |||
2741 | 3203 | ||
2742 | if (decoded_idx == -1) { | 3204 | if (decoded_idx == -1) { |
2743 | /* no frame was decoded, but we might have a display frame */ | 3205 | /* no frame was decoded, but we might have a display frame */ |
2744 | if (display_idx < 0 && ctx->display_idx < 0) | 3206 | if (display_idx >= 0 && display_idx < ctx->num_internal_frames) |
2745 | ctx->prescan_failed = true; | 3207 | ctx->sequence_offset++; |
3208 | else if (ctx->display_idx < 0) | ||
3209 | ctx->hold = true; | ||
2746 | } else if (decoded_idx == -2) { | 3210 | } else if (decoded_idx == -2) { |
2747 | /* no frame was decoded, we still return the remaining buffers */ | 3211 | /* no frame was decoded, we still return the remaining buffers */ |
2748 | } else if (decoded_idx < 0 || decoded_idx >= ctx->num_internal_frames) { | 3212 | } else if (decoded_idx < 0 || decoded_idx >= ctx->num_internal_frames) { |
2749 | v4l2_err(&dev->v4l2_dev, | 3213 | v4l2_err(&dev->v4l2_dev, |
2750 | "decoded frame index out of range: %d\n", decoded_idx); | 3214 | "decoded frame index out of range: %d\n", decoded_idx); |
3215 | } else { | ||
3216 | ts = list_first_entry(&ctx->timestamp_list, | ||
3217 | struct coda_timestamp, list); | ||
3218 | list_del(&ts->list); | ||
3219 | val = coda_read(dev, CODA_RET_DEC_PIC_FRAME_NUM) - 1; | ||
3220 | val -= ctx->sequence_offset; | ||
3221 | if (val != (ts->sequence & 0xffff)) { | ||
3222 | v4l2_err(&dev->v4l2_dev, | ||
3223 | "sequence number mismatch (%d(%d) != %d)\n", | ||
3224 | val, ctx->sequence_offset, ts->sequence); | ||
3225 | } | ||
3226 | ctx->frame_timestamps[decoded_idx] = *ts; | ||
3227 | kfree(ts); | ||
3228 | |||
3229 | val = coda_read(dev, CODA_RET_DEC_PIC_TYPE) & 0x7; | ||
3230 | if (val == 0) | ||
3231 | ctx->frame_types[decoded_idx] = V4L2_BUF_FLAG_KEYFRAME; | ||
3232 | else if (val == 1) | ||
3233 | ctx->frame_types[decoded_idx] = V4L2_BUF_FLAG_PFRAME; | ||
3234 | else | ||
3235 | ctx->frame_types[decoded_idx] = V4L2_BUF_FLAG_BFRAME; | ||
3236 | |||
3237 | ctx->frame_errors[decoded_idx] = err_mb; | ||
2751 | } | 3238 | } |
2752 | 3239 | ||
2753 | if (display_idx == -1) { | 3240 | if (display_idx == -1) { |
@@ -2755,7 +3242,7 @@ static void coda_finish_decode(struct coda_ctx *ctx) | |||
2755 | * no more frames to be decoded, but there could still | 3242 | * no more frames to be decoded, but there could still |
2756 | * be rotator output to dequeue | 3243 | * be rotator output to dequeue |
2757 | */ | 3244 | */ |
2758 | ctx->prescan_failed = true; | 3245 | ctx->hold = true; |
2759 | } else if (display_idx == -3) { | 3246 | } else if (display_idx == -3) { |
2760 | /* possibly prescan failure */ | 3247 | /* possibly prescan failure */ |
2761 | } else if (display_idx < 0 || display_idx >= ctx->num_internal_frames) { | 3248 | } else if (display_idx < 0 || display_idx >= ctx->num_internal_frames) { |
@@ -2767,13 +3254,21 @@ static void coda_finish_decode(struct coda_ctx *ctx) | |||
2767 | /* If a frame was copied out, return it */ | 3254 | /* If a frame was copied out, return it */ |
2768 | if (ctx->display_idx >= 0 && | 3255 | if (ctx->display_idx >= 0 && |
2769 | ctx->display_idx < ctx->num_internal_frames) { | 3256 | ctx->display_idx < ctx->num_internal_frames) { |
2770 | dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); | 3257 | dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); |
2771 | dst_buf->v4l2_buf.sequence = ctx->osequence++; | 3258 | dst_buf->v4l2_buf.sequence = ctx->osequence++; |
2772 | 3259 | ||
3260 | dst_buf->v4l2_buf.flags &= ~(V4L2_BUF_FLAG_KEYFRAME | | ||
3261 | V4L2_BUF_FLAG_PFRAME | | ||
3262 | V4L2_BUF_FLAG_BFRAME); | ||
3263 | dst_buf->v4l2_buf.flags |= ctx->frame_types[ctx->display_idx]; | ||
3264 | ts = &ctx->frame_timestamps[ctx->display_idx]; | ||
3265 | dst_buf->v4l2_buf.timecode = ts->timecode; | ||
3266 | dst_buf->v4l2_buf.timestamp = ts->timestamp; | ||
3267 | |||
2773 | vb2_set_plane_payload(dst_buf, 0, width * height * 3 / 2); | 3268 | vb2_set_plane_payload(dst_buf, 0, width * height * 3 / 2); |
2774 | 3269 | ||
2775 | v4l2_m2m_buf_done(dst_buf, success ? VB2_BUF_STATE_DONE : | 3270 | v4l2_m2m_buf_done(dst_buf, ctx->frame_errors[display_idx] ? |
2776 | VB2_BUF_STATE_ERROR); | 3271 | VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); |
2777 | 3272 | ||
2778 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, | 3273 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, |
2779 | "job finished: decoding frame (%d) (%s)\n", | 3274 | "job finished: decoding frame (%d) (%s)\n", |
@@ -2795,8 +3290,8 @@ static void coda_finish_encode(struct coda_ctx *ctx) | |||
2795 | struct coda_dev *dev = ctx->dev; | 3290 | struct coda_dev *dev = ctx->dev; |
2796 | u32 wr_ptr, start_ptr; | 3291 | u32 wr_ptr, start_ptr; |
2797 | 3292 | ||
2798 | src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); | 3293 | src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); |
2799 | dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); | 3294 | dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); |
2800 | 3295 | ||
2801 | /* Get results from the coda */ | 3296 | /* Get results from the coda */ |
2802 | start_ptr = coda_read(dev, CODA_CMD_ENC_PIC_BB_START); | 3297 | start_ptr = coda_read(dev, CODA_CMD_ENC_PIC_BB_START); |
@@ -2833,6 +3328,8 @@ static void coda_finish_encode(struct coda_ctx *ctx) | |||
2833 | dst_buf->v4l2_buf.timecode = src_buf->v4l2_buf.timecode; | 3328 | dst_buf->v4l2_buf.timecode = src_buf->v4l2_buf.timecode; |
2834 | 3329 | ||
2835 | v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); | 3330 | v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); |
3331 | |||
3332 | dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); | ||
2836 | v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); | 3333 | v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); |
2837 | 3334 | ||
2838 | ctx->gopcounter--; | 3335 | ctx->gopcounter--; |
@@ -2851,8 +3348,6 @@ static irqreturn_t coda_irq_handler(int irq, void *data) | |||
2851 | struct coda_dev *dev = data; | 3348 | struct coda_dev *dev = data; |
2852 | struct coda_ctx *ctx; | 3349 | struct coda_ctx *ctx; |
2853 | 3350 | ||
2854 | cancel_delayed_work(&dev->timeout); | ||
2855 | |||
2856 | /* read status register to attend the IRQ */ | 3351 | /* read status register to attend the IRQ */ |
2857 | coda_read(dev, CODA_REG_BIT_INT_STATUS); | 3352 | coda_read(dev, CODA_REG_BIT_INT_STATUS); |
2858 | coda_write(dev, CODA_REG_BIT_INT_CLEAR_SET, | 3353 | coda_write(dev, CODA_REG_BIT_INT_CLEAR_SET, |
@@ -2868,7 +3363,6 @@ static irqreturn_t coda_irq_handler(int irq, void *data) | |||
2868 | if (ctx->aborting) { | 3363 | if (ctx->aborting) { |
2869 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, | 3364 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, |
2870 | "task has been aborted\n"); | 3365 | "task has been aborted\n"); |
2871 | goto out; | ||
2872 | } | 3366 | } |
2873 | 3367 | ||
2874 | if (coda_isbusy(ctx->dev)) { | 3368 | if (coda_isbusy(ctx->dev)) { |
@@ -2877,60 +3371,15 @@ static irqreturn_t coda_irq_handler(int irq, void *data) | |||
2877 | return IRQ_NONE; | 3371 | return IRQ_NONE; |
2878 | } | 3372 | } |
2879 | 3373 | ||
2880 | if (ctx->inst_type == CODA_INST_DECODER) | 3374 | complete(&ctx->completion); |
2881 | coda_finish_decode(ctx); | ||
2882 | else | ||
2883 | coda_finish_encode(ctx); | ||
2884 | |||
2885 | out: | ||
2886 | if (ctx->aborting || (!ctx->streamon_cap && !ctx->streamon_out)) { | ||
2887 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, | ||
2888 | "%s: sent command 'SEQ_END' to coda\n", __func__); | ||
2889 | if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) { | ||
2890 | v4l2_err(&dev->v4l2_dev, | ||
2891 | "CODA_COMMAND_SEQ_END failed\n"); | ||
2892 | } | ||
2893 | |||
2894 | kfifo_init(&ctx->bitstream_fifo, | ||
2895 | ctx->bitstream.vaddr, ctx->bitstream.size); | ||
2896 | |||
2897 | coda_free_framebuffers(ctx); | ||
2898 | coda_free_context_buffers(ctx); | ||
2899 | } | ||
2900 | |||
2901 | mutex_unlock(&dev->coda_mutex); | ||
2902 | mutex_unlock(&ctx->buffer_mutex); | ||
2903 | |||
2904 | v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->m2m_ctx); | ||
2905 | 3375 | ||
2906 | return IRQ_HANDLED; | 3376 | return IRQ_HANDLED; |
2907 | } | 3377 | } |
2908 | 3378 | ||
2909 | static void coda_timeout(struct work_struct *work) | ||
2910 | { | ||
2911 | struct coda_ctx *ctx; | ||
2912 | struct coda_dev *dev = container_of(to_delayed_work(work), | ||
2913 | struct coda_dev, timeout); | ||
2914 | |||
2915 | dev_err(&dev->plat_dev->dev, "CODA PIC_RUN timeout, stopping all streams\n"); | ||
2916 | |||
2917 | mutex_lock(&dev->dev_mutex); | ||
2918 | list_for_each_entry(ctx, &dev->instances, list) { | ||
2919 | if (mutex_is_locked(&ctx->buffer_mutex)) | ||
2920 | mutex_unlock(&ctx->buffer_mutex); | ||
2921 | v4l2_m2m_streamoff(NULL, ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | ||
2922 | v4l2_m2m_streamoff(NULL, ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); | ||
2923 | } | ||
2924 | mutex_unlock(&dev->dev_mutex); | ||
2925 | |||
2926 | mutex_unlock(&dev->coda_mutex); | ||
2927 | ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev); | ||
2928 | v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->m2m_ctx); | ||
2929 | } | ||
2930 | |||
2931 | static u32 coda_supported_firmwares[] = { | 3379 | static u32 coda_supported_firmwares[] = { |
2932 | CODA_FIRMWARE_VERNUM(CODA_DX6, 2, 2, 5), | 3380 | CODA_FIRMWARE_VERNUM(CODA_DX6, 2, 2, 5), |
2933 | CODA_FIRMWARE_VERNUM(CODA_7541, 1, 4, 50), | 3381 | CODA_FIRMWARE_VERNUM(CODA_7541, 1, 4, 50), |
3382 | CODA_FIRMWARE_VERNUM(CODA_960, 2, 1, 5), | ||
2934 | }; | 3383 | }; |
2935 | 3384 | ||
2936 | static bool coda_firmware_supported(u32 vernum) | 3385 | static bool coda_firmware_supported(u32 vernum) |
@@ -2945,19 +3394,21 @@ static bool coda_firmware_supported(u32 vernum) | |||
2945 | 3394 | ||
2946 | static int coda_hw_init(struct coda_dev *dev) | 3395 | static int coda_hw_init(struct coda_dev *dev) |
2947 | { | 3396 | { |
2948 | u16 product, major, minor, release; | ||
2949 | u32 data; | 3397 | u32 data; |
2950 | u16 *p; | 3398 | u16 *p; |
2951 | int i, ret; | 3399 | int i, ret; |
2952 | 3400 | ||
2953 | ret = clk_prepare_enable(dev->clk_per); | 3401 | ret = clk_prepare_enable(dev->clk_per); |
2954 | if (ret) | 3402 | if (ret) |
2955 | return ret; | 3403 | goto err_clk_per; |
2956 | 3404 | ||
2957 | ret = clk_prepare_enable(dev->clk_ahb); | 3405 | ret = clk_prepare_enable(dev->clk_ahb); |
2958 | if (ret) | 3406 | if (ret) |
2959 | goto err_clk_ahb; | 3407 | goto err_clk_ahb; |
2960 | 3408 | ||
3409 | if (dev->rstc) | ||
3410 | reset_control_reset(dev->rstc); | ||
3411 | |||
2961 | /* | 3412 | /* |
2962 | * Copy the first CODA_ISRAM_SIZE in the internal SRAM. | 3413 | * Copy the first CODA_ISRAM_SIZE in the internal SRAM. |
2963 | * The 16-bit chars in the code buffer are in memory access | 3414 | * The 16-bit chars in the code buffer are in memory access |
@@ -2985,7 +3436,8 @@ static int coda_hw_init(struct coda_dev *dev) | |||
2985 | coda_write(dev, 0, CODA_REG_BIT_CODE_BUF_ADDR + i * 4); | 3436 | coda_write(dev, 0, CODA_REG_BIT_CODE_BUF_ADDR + i * 4); |
2986 | 3437 | ||
2987 | /* Tell the BIT where to find everything it needs */ | 3438 | /* Tell the BIT where to find everything it needs */ |
2988 | if (dev->devtype->product == CODA_7541) { | 3439 | if (dev->devtype->product == CODA_960 || |
3440 | dev->devtype->product == CODA_7541) { | ||
2989 | coda_write(dev, dev->tempbuf.paddr, | 3441 | coda_write(dev, dev->tempbuf.paddr, |
2990 | CODA_REG_BIT_TEMP_BUF_ADDR); | 3442 | CODA_REG_BIT_TEMP_BUF_ADDR); |
2991 | coda_write(dev, 0, CODA_REG_BIT_BIT_STREAM_PARAM); | 3443 | coda_write(dev, 0, CODA_REG_BIT_BIT_STREAM_PARAM); |
@@ -3005,7 +3457,10 @@ static int coda_hw_init(struct coda_dev *dev) | |||
3005 | default: | 3457 | default: |
3006 | coda_write(dev, CODA7_STREAM_BUF_PIC_FLUSH, CODA_REG_BIT_STREAM_CTRL); | 3458 | coda_write(dev, CODA7_STREAM_BUF_PIC_FLUSH, CODA_REG_BIT_STREAM_CTRL); |
3007 | } | 3459 | } |
3008 | coda_write(dev, 0, CODA_REG_BIT_FRAME_MEM_CTRL); | 3460 | if (dev->devtype->product == CODA_960) |
3461 | coda_write(dev, 1 << 12, CODA_REG_BIT_FRAME_MEM_CTRL); | ||
3462 | else | ||
3463 | coda_write(dev, 0, CODA_REG_BIT_FRAME_MEM_CTRL); | ||
3009 | 3464 | ||
3010 | if (dev->devtype->product != CODA_DX6) | 3465 | if (dev->devtype->product != CODA_DX6) |
3011 | coda_write(dev, 0, CODA7_REG_BIT_AXI_SRAM_USE); | 3466 | coda_write(dev, 0, CODA7_REG_BIT_AXI_SRAM_USE); |
@@ -3022,17 +3477,46 @@ static int coda_hw_init(struct coda_dev *dev) | |||
3022 | coda_write(dev, data, CODA_REG_BIT_CODE_RESET); | 3477 | coda_write(dev, data, CODA_REG_BIT_CODE_RESET); |
3023 | coda_write(dev, CODA_REG_RUN_ENABLE, CODA_REG_BIT_CODE_RUN); | 3478 | coda_write(dev, CODA_REG_RUN_ENABLE, CODA_REG_BIT_CODE_RUN); |
3024 | 3479 | ||
3025 | /* Load firmware */ | 3480 | clk_disable_unprepare(dev->clk_ahb); |
3481 | clk_disable_unprepare(dev->clk_per); | ||
3482 | |||
3483 | return 0; | ||
3484 | |||
3485 | err_clk_ahb: | ||
3486 | clk_disable_unprepare(dev->clk_per); | ||
3487 | err_clk_per: | ||
3488 | return ret; | ||
3489 | } | ||
3490 | |||
3491 | static int coda_check_firmware(struct coda_dev *dev) | ||
3492 | { | ||
3493 | u16 product, major, minor, release; | ||
3494 | u32 data; | ||
3495 | int ret; | ||
3496 | |||
3497 | ret = clk_prepare_enable(dev->clk_per); | ||
3498 | if (ret) | ||
3499 | goto err_clk_per; | ||
3500 | |||
3501 | ret = clk_prepare_enable(dev->clk_ahb); | ||
3502 | if (ret) | ||
3503 | goto err_clk_ahb; | ||
3504 | |||
3026 | coda_write(dev, 0, CODA_CMD_FIRMWARE_VERNUM); | 3505 | coda_write(dev, 0, CODA_CMD_FIRMWARE_VERNUM); |
3027 | coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY); | 3506 | coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY); |
3028 | coda_write(dev, 0, CODA_REG_BIT_RUN_INDEX); | 3507 | coda_write(dev, 0, CODA_REG_BIT_RUN_INDEX); |
3029 | coda_write(dev, 0, CODA_REG_BIT_RUN_COD_STD); | 3508 | coda_write(dev, 0, CODA_REG_BIT_RUN_COD_STD); |
3030 | coda_write(dev, CODA_COMMAND_FIRMWARE_GET, CODA_REG_BIT_RUN_COMMAND); | 3509 | coda_write(dev, CODA_COMMAND_FIRMWARE_GET, CODA_REG_BIT_RUN_COMMAND); |
3031 | if (coda_wait_timeout(dev)) { | 3510 | if (coda_wait_timeout(dev)) { |
3032 | clk_disable_unprepare(dev->clk_per); | ||
3033 | clk_disable_unprepare(dev->clk_ahb); | ||
3034 | v4l2_err(&dev->v4l2_dev, "firmware get command error\n"); | 3511 | v4l2_err(&dev->v4l2_dev, "firmware get command error\n"); |
3035 | return -EIO; | 3512 | ret = -EIO; |
3513 | goto err_run_cmd; | ||
3514 | } | ||
3515 | |||
3516 | if (dev->devtype->product == CODA_960) { | ||
3517 | data = coda_read(dev, CODA9_CMD_FIRMWARE_CODE_REV); | ||
3518 | v4l2_info(&dev->v4l2_dev, "Firmware code revision: %d\n", | ||
3519 | data); | ||
3036 | } | 3520 | } |
3037 | 3521 | ||
3038 | /* Check we are compatible with the loaded firmware */ | 3522 | /* Check we are compatible with the loaded firmware */ |
@@ -3066,8 +3550,11 @@ static int coda_hw_init(struct coda_dev *dev) | |||
3066 | 3550 | ||
3067 | return 0; | 3551 | return 0; |
3068 | 3552 | ||
3553 | err_run_cmd: | ||
3554 | clk_disable_unprepare(dev->clk_ahb); | ||
3069 | err_clk_ahb: | 3555 | err_clk_ahb: |
3070 | clk_disable_unprepare(dev->clk_per); | 3556 | clk_disable_unprepare(dev->clk_per); |
3557 | err_clk_per: | ||
3071 | return ret; | 3558 | return ret; |
3072 | } | 3559 | } |
3073 | 3560 | ||
@@ -3083,7 +3570,8 @@ static void coda_fw_callback(const struct firmware *fw, void *context) | |||
3083 | } | 3570 | } |
3084 | 3571 | ||
3085 | /* allocate auxiliary per-device code buffer for the BIT processor */ | 3572 | /* allocate auxiliary per-device code buffer for the BIT processor */ |
3086 | ret = coda_alloc_aux_buf(dev, &dev->codebuf, fw->size); | 3573 | ret = coda_alloc_aux_buf(dev, &dev->codebuf, fw->size, "codebuf", |
3574 | dev->debugfs_root); | ||
3087 | if (ret < 0) { | 3575 | if (ret < 0) { |
3088 | dev_err(&pdev->dev, "failed to allocate code buffer\n"); | 3576 | dev_err(&pdev->dev, "failed to allocate code buffer\n"); |
3089 | return; | 3577 | return; |
@@ -3093,10 +3581,37 @@ static void coda_fw_callback(const struct firmware *fw, void *context) | |||
3093 | memcpy(dev->codebuf.vaddr, fw->data, fw->size); | 3581 | memcpy(dev->codebuf.vaddr, fw->data, fw->size); |
3094 | release_firmware(fw); | 3582 | release_firmware(fw); |
3095 | 3583 | ||
3096 | ret = coda_hw_init(dev); | 3584 | if (pm_runtime_enabled(&pdev->dev) && pdev->dev.pm_domain) { |
3097 | if (ret) { | 3585 | /* |
3098 | v4l2_err(&dev->v4l2_dev, "HW initialization failed\n"); | 3586 | * Enabling power temporarily will cause coda_hw_init to be |
3099 | return; | 3587 | * called via coda_runtime_resume by the pm domain. |
3588 | */ | ||
3589 | ret = pm_runtime_get_sync(&dev->plat_dev->dev); | ||
3590 | if (ret < 0) { | ||
3591 | v4l2_err(&dev->v4l2_dev, "failed to power on: %d\n", | ||
3592 | ret); | ||
3593 | return; | ||
3594 | } | ||
3595 | |||
3596 | ret = coda_check_firmware(dev); | ||
3597 | if (ret < 0) | ||
3598 | return; | ||
3599 | |||
3600 | pm_runtime_put_sync(&dev->plat_dev->dev); | ||
3601 | } else { | ||
3602 | /* | ||
3603 | * If runtime pm is disabled or pm_domain is not set, | ||
3604 | * initialize once manually. | ||
3605 | */ | ||
3606 | ret = coda_hw_init(dev); | ||
3607 | if (ret < 0) { | ||
3608 | v4l2_err(&dev->v4l2_dev, "HW initialization failed\n"); | ||
3609 | return; | ||
3610 | } | ||
3611 | |||
3612 | ret = coda_check_firmware(dev); | ||
3613 | if (ret < 0) | ||
3614 | return; | ||
3100 | } | 3615 | } |
3101 | 3616 | ||
3102 | dev->vfd.fops = &coda_fops, | 3617 | dev->vfd.fops = &coda_fops, |
@@ -3150,20 +3665,45 @@ static int coda_firmware_request(struct coda_dev *dev) | |||
3150 | enum coda_platform { | 3665 | enum coda_platform { |
3151 | CODA_IMX27, | 3666 | CODA_IMX27, |
3152 | CODA_IMX53, | 3667 | CODA_IMX53, |
3668 | CODA_IMX6Q, | ||
3669 | CODA_IMX6DL, | ||
3153 | }; | 3670 | }; |
3154 | 3671 | ||
3155 | static const struct coda_devtype coda_devdata[] = { | 3672 | static const struct coda_devtype coda_devdata[] = { |
3156 | [CODA_IMX27] = { | 3673 | [CODA_IMX27] = { |
3157 | .firmware = "v4l-codadx6-imx27.bin", | 3674 | .firmware = "v4l-codadx6-imx27.bin", |
3158 | .product = CODA_DX6, | 3675 | .product = CODA_DX6, |
3159 | .codecs = codadx6_codecs, | 3676 | .codecs = codadx6_codecs, |
3160 | .num_codecs = ARRAY_SIZE(codadx6_codecs), | 3677 | .num_codecs = ARRAY_SIZE(codadx6_codecs), |
3678 | .workbuf_size = 288 * 1024 + FMO_SLICE_SAVE_BUF_SIZE * 8 * 1024, | ||
3679 | .iram_size = 0xb000, | ||
3161 | }, | 3680 | }, |
3162 | [CODA_IMX53] = { | 3681 | [CODA_IMX53] = { |
3163 | .firmware = "v4l-coda7541-imx53.bin", | 3682 | .firmware = "v4l-coda7541-imx53.bin", |
3164 | .product = CODA_7541, | 3683 | .product = CODA_7541, |
3165 | .codecs = coda7_codecs, | 3684 | .codecs = coda7_codecs, |
3166 | .num_codecs = ARRAY_SIZE(coda7_codecs), | 3685 | .num_codecs = ARRAY_SIZE(coda7_codecs), |
3686 | .workbuf_size = 128 * 1024, | ||
3687 | .tempbuf_size = 304 * 1024, | ||
3688 | .iram_size = 0x14000, | ||
3689 | }, | ||
3690 | [CODA_IMX6Q] = { | ||
3691 | .firmware = "v4l-coda960-imx6q.bin", | ||
3692 | .product = CODA_960, | ||
3693 | .codecs = coda9_codecs, | ||
3694 | .num_codecs = ARRAY_SIZE(coda9_codecs), | ||
3695 | .workbuf_size = 80 * 1024, | ||
3696 | .tempbuf_size = 204 * 1024, | ||
3697 | .iram_size = 0x21000, | ||
3698 | }, | ||
3699 | [CODA_IMX6DL] = { | ||
3700 | .firmware = "v4l-coda960-imx6dl.bin", | ||
3701 | .product = CODA_960, | ||
3702 | .codecs = coda9_codecs, | ||
3703 | .num_codecs = ARRAY_SIZE(coda9_codecs), | ||
3704 | .workbuf_size = 80 * 1024, | ||
3705 | .tempbuf_size = 204 * 1024, | ||
3706 | .iram_size = 0x20000, | ||
3167 | }, | 3707 | }, |
3168 | }; | 3708 | }; |
3169 | 3709 | ||
@@ -3178,6 +3718,8 @@ MODULE_DEVICE_TABLE(platform, coda_platform_ids); | |||
3178 | static const struct of_device_id coda_dt_ids[] = { | 3718 | static const struct of_device_id coda_dt_ids[] = { |
3179 | { .compatible = "fsl,imx27-vpu", .data = &coda_devdata[CODA_IMX27] }, | 3719 | { .compatible = "fsl,imx27-vpu", .data = &coda_devdata[CODA_IMX27] }, |
3180 | { .compatible = "fsl,imx53-vpu", .data = &coda_devdata[CODA_IMX53] }, | 3720 | { .compatible = "fsl,imx53-vpu", .data = &coda_devdata[CODA_IMX53] }, |
3721 | { .compatible = "fsl,imx6q-vpu", .data = &coda_devdata[CODA_IMX6Q] }, | ||
3722 | { .compatible = "fsl,imx6dl-vpu", .data = &coda_devdata[CODA_IMX6DL] }, | ||
3181 | { /* sentinel */ } | 3723 | { /* sentinel */ } |
3182 | }; | 3724 | }; |
3183 | MODULE_DEVICE_TABLE(of, coda_dt_ids); | 3725 | MODULE_DEVICE_TABLE(of, coda_dt_ids); |
@@ -3204,7 +3746,6 @@ static int coda_probe(struct platform_device *pdev) | |||
3204 | 3746 | ||
3205 | spin_lock_init(&dev->irqlock); | 3747 | spin_lock_init(&dev->irqlock); |
3206 | INIT_LIST_HEAD(&dev->instances); | 3748 | INIT_LIST_HEAD(&dev->instances); |
3207 | INIT_DELAYED_WORK(&dev->timeout, coda_timeout); | ||
3208 | 3749 | ||
3209 | dev->plat_dev = pdev; | 3750 | dev->plat_dev = pdev; |
3210 | dev->clk_per = devm_clk_get(&pdev->dev, "per"); | 3751 | dev->clk_per = devm_clk_get(&pdev->dev, "per"); |
@@ -3229,13 +3770,25 @@ static int coda_probe(struct platform_device *pdev) | |||
3229 | irq = platform_get_irq(pdev, 0); | 3770 | irq = platform_get_irq(pdev, 0); |
3230 | if (irq < 0) { | 3771 | if (irq < 0) { |
3231 | dev_err(&pdev->dev, "failed to get irq resource\n"); | 3772 | dev_err(&pdev->dev, "failed to get irq resource\n"); |
3232 | return -ENOENT; | 3773 | return irq; |
3233 | } | 3774 | } |
3234 | 3775 | ||
3235 | if (devm_request_threaded_irq(&pdev->dev, irq, NULL, coda_irq_handler, | 3776 | ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, coda_irq_handler, |
3236 | IRQF_ONESHOT, dev_name(&pdev->dev), dev) < 0) { | 3777 | IRQF_ONESHOT, dev_name(&pdev->dev), dev); |
3237 | dev_err(&pdev->dev, "failed to request irq\n"); | 3778 | if (ret < 0) { |
3238 | return -ENOENT; | 3779 | dev_err(&pdev->dev, "failed to request irq: %d\n", ret); |
3780 | return ret; | ||
3781 | } | ||
3782 | |||
3783 | dev->rstc = devm_reset_control_get_optional(&pdev->dev, NULL); | ||
3784 | if (IS_ERR(dev->rstc)) { | ||
3785 | ret = PTR_ERR(dev->rstc); | ||
3786 | if (ret == -ENOENT || ret == -ENOSYS) { | ||
3787 | dev->rstc = NULL; | ||
3788 | } else { | ||
3789 | dev_err(&pdev->dev, "failed get reset control: %d\n", ret); | ||
3790 | return ret; | ||
3791 | } | ||
3239 | } | 3792 | } |
3240 | 3793 | ||
3241 | /* Get IRAM pool from device tree or platform data */ | 3794 | /* Get IRAM pool from device tree or platform data */ |
@@ -3266,24 +3819,26 @@ static int coda_probe(struct platform_device *pdev) | |||
3266 | return -EINVAL; | 3819 | return -EINVAL; |
3267 | } | 3820 | } |
3268 | 3821 | ||
3822 | dev->debugfs_root = debugfs_create_dir("coda", NULL); | ||
3823 | if (!dev->debugfs_root) | ||
3824 | dev_warn(&pdev->dev, "failed to create debugfs root\n"); | ||
3825 | |||
3269 | /* allocate auxiliary per-device buffers for the BIT processor */ | 3826 | /* allocate auxiliary per-device buffers for the BIT processor */ |
3270 | switch (dev->devtype->product) { | 3827 | if (dev->devtype->product == CODA_DX6) { |
3271 | case CODA_DX6: | ||
3272 | ret = coda_alloc_aux_buf(dev, &dev->workbuf, | 3828 | ret = coda_alloc_aux_buf(dev, &dev->workbuf, |
3273 | CODADX6_WORK_BUF_SIZE); | 3829 | dev->devtype->workbuf_size, "workbuf", |
3830 | dev->debugfs_root); | ||
3274 | if (ret < 0) { | 3831 | if (ret < 0) { |
3275 | dev_err(&pdev->dev, "failed to allocate work buffer\n"); | 3832 | dev_err(&pdev->dev, "failed to allocate work buffer\n"); |
3276 | v4l2_device_unregister(&dev->v4l2_dev); | 3833 | v4l2_device_unregister(&dev->v4l2_dev); |
3277 | return ret; | 3834 | return ret; |
3278 | } | 3835 | } |
3279 | break; | ||
3280 | case CODA_7541: | ||
3281 | dev->tempbuf.size = CODA7_TEMP_BUF_SIZE; | ||
3282 | break; | ||
3283 | } | 3836 | } |
3284 | if (dev->tempbuf.size) { | 3837 | |
3838 | if (dev->devtype->tempbuf_size) { | ||
3285 | ret = coda_alloc_aux_buf(dev, &dev->tempbuf, | 3839 | ret = coda_alloc_aux_buf(dev, &dev->tempbuf, |
3286 | dev->tempbuf.size); | 3840 | dev->devtype->tempbuf_size, "tempbuf", |
3841 | dev->debugfs_root); | ||
3287 | if (ret < 0) { | 3842 | if (ret < 0) { |
3288 | dev_err(&pdev->dev, "failed to allocate temp buffer\n"); | 3843 | dev_err(&pdev->dev, "failed to allocate temp buffer\n"); |
3289 | v4l2_device_unregister(&dev->v4l2_dev); | 3844 | v4l2_device_unregister(&dev->v4l2_dev); |
@@ -3291,23 +3846,29 @@ static int coda_probe(struct platform_device *pdev) | |||
3291 | } | 3846 | } |
3292 | } | 3847 | } |
3293 | 3848 | ||
3294 | switch (dev->devtype->product) { | 3849 | dev->iram.size = dev->devtype->iram_size; |
3295 | case CODA_DX6: | 3850 | dev->iram.vaddr = gen_pool_dma_alloc(dev->iram_pool, dev->iram.size, |
3296 | dev->iram_size = CODADX6_IRAM_SIZE; | 3851 | &dev->iram.paddr); |
3297 | break; | 3852 | if (!dev->iram.vaddr) { |
3298 | case CODA_7541: | ||
3299 | dev->iram_size = CODA7_IRAM_SIZE; | ||
3300 | break; | ||
3301 | } | ||
3302 | dev->iram_vaddr = (unsigned long)gen_pool_dma_alloc(dev->iram_pool, | ||
3303 | dev->iram_size, (dma_addr_t *)&dev->iram_paddr); | ||
3304 | if (!dev->iram_vaddr) { | ||
3305 | dev_err(&pdev->dev, "unable to alloc iram\n"); | 3853 | dev_err(&pdev->dev, "unable to alloc iram\n"); |
3306 | return -ENOMEM; | 3854 | return -ENOMEM; |
3307 | } | 3855 | } |
3308 | 3856 | ||
3857 | dev->iram.blob.data = dev->iram.vaddr; | ||
3858 | dev->iram.blob.size = dev->iram.size; | ||
3859 | dev->iram.dentry = debugfs_create_blob("iram", 0644, dev->debugfs_root, | ||
3860 | &dev->iram.blob); | ||
3861 | |||
3862 | dev->workqueue = alloc_workqueue("coda", WQ_UNBOUND | WQ_MEM_RECLAIM, 1); | ||
3863 | if (!dev->workqueue) { | ||
3864 | dev_err(&pdev->dev, "unable to alloc workqueue\n"); | ||
3865 | return -ENOMEM; | ||
3866 | } | ||
3867 | |||
3309 | platform_set_drvdata(pdev, dev); | 3868 | platform_set_drvdata(pdev, dev); |
3310 | 3869 | ||
3870 | pm_runtime_enable(&pdev->dev); | ||
3871 | |||
3311 | return coda_firmware_request(dev); | 3872 | return coda_firmware_request(dev); |
3312 | } | 3873 | } |
3313 | 3874 | ||
@@ -3318,17 +3879,41 @@ static int coda_remove(struct platform_device *pdev) | |||
3318 | video_unregister_device(&dev->vfd); | 3879 | video_unregister_device(&dev->vfd); |
3319 | if (dev->m2m_dev) | 3880 | if (dev->m2m_dev) |
3320 | v4l2_m2m_release(dev->m2m_dev); | 3881 | v4l2_m2m_release(dev->m2m_dev); |
3882 | pm_runtime_disable(&pdev->dev); | ||
3321 | if (dev->alloc_ctx) | 3883 | if (dev->alloc_ctx) |
3322 | vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); | 3884 | vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); |
3323 | v4l2_device_unregister(&dev->v4l2_dev); | 3885 | v4l2_device_unregister(&dev->v4l2_dev); |
3324 | if (dev->iram_vaddr) | 3886 | destroy_workqueue(dev->workqueue); |
3325 | gen_pool_free(dev->iram_pool, dev->iram_vaddr, dev->iram_size); | 3887 | if (dev->iram.vaddr) |
3888 | gen_pool_free(dev->iram_pool, (unsigned long)dev->iram.vaddr, | ||
3889 | dev->iram.size); | ||
3326 | coda_free_aux_buf(dev, &dev->codebuf); | 3890 | coda_free_aux_buf(dev, &dev->codebuf); |
3327 | coda_free_aux_buf(dev, &dev->tempbuf); | 3891 | coda_free_aux_buf(dev, &dev->tempbuf); |
3328 | coda_free_aux_buf(dev, &dev->workbuf); | 3892 | coda_free_aux_buf(dev, &dev->workbuf); |
3893 | debugfs_remove_recursive(dev->debugfs_root); | ||
3329 | return 0; | 3894 | return 0; |
3330 | } | 3895 | } |
3331 | 3896 | ||
3897 | #ifdef CONFIG_PM_RUNTIME | ||
3898 | static int coda_runtime_resume(struct device *dev) | ||
3899 | { | ||
3900 | struct coda_dev *cdev = dev_get_drvdata(dev); | ||
3901 | int ret = 0; | ||
3902 | |||
3903 | if (dev->pm_domain) { | ||
3904 | ret = coda_hw_init(cdev); | ||
3905 | if (ret) | ||
3906 | v4l2_err(&cdev->v4l2_dev, "HW initialization failed\n"); | ||
3907 | } | ||
3908 | |||
3909 | return ret; | ||
3910 | } | ||
3911 | #endif | ||
3912 | |||
3913 | static const struct dev_pm_ops coda_pm_ops = { | ||
3914 | SET_RUNTIME_PM_OPS(NULL, coda_runtime_resume, NULL) | ||
3915 | }; | ||
3916 | |||
3332 | static struct platform_driver coda_driver = { | 3917 | static struct platform_driver coda_driver = { |
3333 | .probe = coda_probe, | 3918 | .probe = coda_probe, |
3334 | .remove = coda_remove, | 3919 | .remove = coda_remove, |
@@ -3336,6 +3921,7 @@ static struct platform_driver coda_driver = { | |||
3336 | .name = CODA_NAME, | 3921 | .name = CODA_NAME, |
3337 | .owner = THIS_MODULE, | 3922 | .owner = THIS_MODULE, |
3338 | .of_match_table = of_match_ptr(coda_dt_ids), | 3923 | .of_match_table = of_match_ptr(coda_dt_ids), |
3924 | .pm = &coda_pm_ops, | ||
3339 | }, | 3925 | }, |
3340 | .id_table = coda_platform_ids, | 3926 | .id_table = coda_platform_ids, |
3341 | }; | 3927 | }; |
diff --git a/drivers/media/platform/coda.h b/drivers/media/platform/coda.h index 4e32e2edea62..c791275e307b 100644 --- a/drivers/media/platform/coda.h +++ b/drivers/media/platform/coda.h | |||
@@ -27,6 +27,14 @@ | |||
27 | #define CODA_REG_BIT_CODE_RESET 0x014 | 27 | #define CODA_REG_BIT_CODE_RESET 0x014 |
28 | #define CODA_REG_RESET_ENABLE (1 << 0) | 28 | #define CODA_REG_RESET_ENABLE (1 << 0) |
29 | #define CODA_REG_BIT_CUR_PC 0x018 | 29 | #define CODA_REG_BIT_CUR_PC 0x018 |
30 | #define CODA9_REG_BIT_SW_RESET 0x024 | ||
31 | #define CODA9_SW_RESET_BPU_CORE 0x008 | ||
32 | #define CODA9_SW_RESET_BPU_BUS 0x010 | ||
33 | #define CODA9_SW_RESET_VCE_CORE 0x020 | ||
34 | #define CODA9_SW_RESET_VCE_BUS 0x040 | ||
35 | #define CODA9_SW_RESET_GDI_CORE 0x080 | ||
36 | #define CODA9_SW_RESET_GDI_BUS 0x100 | ||
37 | #define CODA9_REG_BIT_SW_RESET_STATUS 0x034 | ||
30 | 38 | ||
31 | /* Static SW registers */ | 39 | /* Static SW registers */ |
32 | #define CODA_REG_BIT_CODE_BUF_ADDR 0x100 | 40 | #define CODA_REG_BIT_CODE_BUF_ADDR 0x100 |
@@ -39,9 +47,11 @@ | |||
39 | #define CODADX6_STREAM_BUF_PIC_FLUSH (1 << 2) | 47 | #define CODADX6_STREAM_BUF_PIC_FLUSH (1 << 2) |
40 | #define CODA7_STREAM_BUF_DYNALLOC_EN (1 << 5) | 48 | #define CODA7_STREAM_BUF_DYNALLOC_EN (1 << 5) |
41 | #define CODADX6_STREAM_BUF_DYNALLOC_EN (1 << 4) | 49 | #define CODADX6_STREAM_BUF_DYNALLOC_EN (1 << 4) |
42 | #define CODA_STREAM_CHKDIS_OFFSET (1 << 1) | 50 | #define CODADX6_STREAM_CHKDIS_OFFSET (1 << 1) |
51 | #define CODA7_STREAM_SEL_64BITS_ENDIAN (1 << 1) | ||
43 | #define CODA_STREAM_ENDIAN_SELECT (1 << 0) | 52 | #define CODA_STREAM_ENDIAN_SELECT (1 << 0) |
44 | #define CODA_REG_BIT_FRAME_MEM_CTRL 0x110 | 53 | #define CODA_REG_BIT_FRAME_MEM_CTRL 0x110 |
54 | #define CODA_FRAME_CHROMA_INTERLEAVE (1 << 2) | ||
45 | #define CODA_IMAGE_ENDIAN_SELECT (1 << 0) | 55 | #define CODA_IMAGE_ENDIAN_SELECT (1 << 0) |
46 | #define CODA_REG_BIT_BIT_STREAM_PARAM 0x114 | 56 | #define CODA_REG_BIT_BIT_STREAM_PARAM 0x114 |
47 | #define CODA_BIT_STREAM_END_FLAG (1 << 2) | 57 | #define CODA_BIT_STREAM_END_FLAG (1 << 2) |
@@ -52,13 +62,21 @@ | |||
52 | #define CODA_REG_BIT_FRM_DIS_FLG(x) (0x150 + 4 * (x)) | 62 | #define CODA_REG_BIT_FRM_DIS_FLG(x) (0x150 + 4 * (x)) |
53 | #define CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR 0x140 | 63 | #define CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR 0x140 |
54 | #define CODA7_REG_BIT_AXI_SRAM_USE 0x140 | 64 | #define CODA7_REG_BIT_AXI_SRAM_USE 0x140 |
65 | #define CODA9_USE_HOST_BTP_ENABLE (1 << 13) | ||
66 | #define CODA9_USE_HOST_OVL_ENABLE (1 << 12) | ||
55 | #define CODA7_USE_HOST_ME_ENABLE (1 << 11) | 67 | #define CODA7_USE_HOST_ME_ENABLE (1 << 11) |
68 | #define CODA9_USE_HOST_DBK_ENABLE (3 << 10) | ||
56 | #define CODA7_USE_HOST_OVL_ENABLE (1 << 10) | 69 | #define CODA7_USE_HOST_OVL_ENABLE (1 << 10) |
57 | #define CODA7_USE_HOST_DBK_ENABLE (1 << 9) | 70 | #define CODA7_USE_HOST_DBK_ENABLE (1 << 9) |
71 | #define CODA9_USE_HOST_IP_ENABLE (1 << 9) | ||
58 | #define CODA7_USE_HOST_IP_ENABLE (1 << 8) | 72 | #define CODA7_USE_HOST_IP_ENABLE (1 << 8) |
73 | #define CODA9_USE_HOST_BIT_ENABLE (1 << 8) | ||
59 | #define CODA7_USE_HOST_BIT_ENABLE (1 << 7) | 74 | #define CODA7_USE_HOST_BIT_ENABLE (1 << 7) |
75 | #define CODA9_USE_BTP_ENABLE (1 << 5) | ||
60 | #define CODA7_USE_ME_ENABLE (1 << 4) | 76 | #define CODA7_USE_ME_ENABLE (1 << 4) |
77 | #define CODA9_USE_OVL_ENABLE (1 << 4) | ||
61 | #define CODA7_USE_OVL_ENABLE (1 << 3) | 78 | #define CODA7_USE_OVL_ENABLE (1 << 3) |
79 | #define CODA9_USE_DBK_ENABLE (3 << 2) | ||
62 | #define CODA7_USE_DBK_ENABLE (1 << 2) | 80 | #define CODA7_USE_DBK_ENABLE (1 << 2) |
63 | #define CODA7_USE_IP_ENABLE (1 << 1) | 81 | #define CODA7_USE_IP_ENABLE (1 << 1) |
64 | #define CODA7_USE_BIT_ENABLE (1 << 0) | 82 | #define CODA7_USE_BIT_ENABLE (1 << 0) |
@@ -93,6 +111,18 @@ | |||
93 | #define CODA7_MODE_ENCODE_H264 8 | 111 | #define CODA7_MODE_ENCODE_H264 8 |
94 | #define CODA7_MODE_ENCODE_MP4 11 | 112 | #define CODA7_MODE_ENCODE_MP4 11 |
95 | #define CODA7_MODE_ENCODE_MJPG 13 | 113 | #define CODA7_MODE_ENCODE_MJPG 13 |
114 | #define CODA9_MODE_DECODE_H264 0 | ||
115 | #define CODA9_MODE_DECODE_VC1 1 | ||
116 | #define CODA9_MODE_DECODE_MP2 2 | ||
117 | #define CODA9_MODE_DECODE_MP4 3 | ||
118 | #define CODA9_MODE_DECODE_DV3 3 | ||
119 | #define CODA9_MODE_DECODE_RV 4 | ||
120 | #define CODA9_MODE_DECODE_AVS 5 | ||
121 | #define CODA9_MODE_DECODE_MJPG 6 | ||
122 | #define CODA9_MODE_DECODE_VPX 7 | ||
123 | #define CODA9_MODE_ENCODE_H264 8 | ||
124 | #define CODA9_MODE_ENCODE_MP4 11 | ||
125 | #define CODA9_MODE_ENCODE_MJPG 13 | ||
96 | #define CODA_MODE_INVALID 0xffff | 126 | #define CODA_MODE_INVALID 0xffff |
97 | #define CODA_REG_BIT_INT_ENABLE 0x170 | 127 | #define CODA_REG_BIT_INT_ENABLE 0x170 |
98 | #define CODA_INT_INTERRUPT_ENABLE (1 << 3) | 128 | #define CODA_INT_INTERRUPT_ENABLE (1 << 3) |
@@ -129,6 +159,7 @@ | |||
129 | #define CODA_CMD_DEC_SEQ_SPP_CHUNK_SIZE 0x1a0 | 159 | #define CODA_CMD_DEC_SEQ_SPP_CHUNK_SIZE 0x1a0 |
130 | 160 | ||
131 | #define CODA7_RET_DEC_SEQ_ASPECT 0x1b0 | 161 | #define CODA7_RET_DEC_SEQ_ASPECT 0x1b0 |
162 | #define CODA9_RET_DEC_SEQ_BITRATE 0x1b4 | ||
132 | #define CODA_RET_DEC_SEQ_SUCCESS 0x1c0 | 163 | #define CODA_RET_DEC_SEQ_SUCCESS 0x1c0 |
133 | #define CODA_RET_DEC_SEQ_SRC_FMT 0x1c4 /* SRC_SIZE on CODA7 */ | 164 | #define CODA_RET_DEC_SEQ_SRC_FMT 0x1c4 /* SRC_SIZE on CODA7 */ |
134 | #define CODA_RET_DEC_SEQ_SRC_SIZE 0x1c4 | 165 | #define CODA_RET_DEC_SEQ_SRC_SIZE 0x1c4 |
@@ -145,13 +176,19 @@ | |||
145 | #define CODA_RET_DEC_SEQ_FRATE_DR 0x1e8 | 176 | #define CODA_RET_DEC_SEQ_FRATE_DR 0x1e8 |
146 | #define CODA_RET_DEC_SEQ_JPG_PARA 0x1e4 | 177 | #define CODA_RET_DEC_SEQ_JPG_PARA 0x1e4 |
147 | #define CODA_RET_DEC_SEQ_JPG_THUMB_IND 0x1e8 | 178 | #define CODA_RET_DEC_SEQ_JPG_THUMB_IND 0x1e8 |
179 | #define CODA9_RET_DEC_SEQ_HEADER_REPORT 0x1ec | ||
148 | 180 | ||
149 | /* Decoder Picture Run */ | 181 | /* Decoder Picture Run */ |
150 | #define CODA_CMD_DEC_PIC_ROT_MODE 0x180 | 182 | #define CODA_CMD_DEC_PIC_ROT_MODE 0x180 |
151 | #define CODA_CMD_DEC_PIC_ROT_ADDR_Y 0x184 | 183 | #define CODA_CMD_DEC_PIC_ROT_ADDR_Y 0x184 |
184 | #define CODA9_CMD_DEC_PIC_ROT_INDEX 0x184 | ||
152 | #define CODA_CMD_DEC_PIC_ROT_ADDR_CB 0x188 | 185 | #define CODA_CMD_DEC_PIC_ROT_ADDR_CB 0x188 |
186 | #define CODA9_CMD_DEC_PIC_ROT_ADDR_Y 0x188 | ||
153 | #define CODA_CMD_DEC_PIC_ROT_ADDR_CR 0x18c | 187 | #define CODA_CMD_DEC_PIC_ROT_ADDR_CR 0x18c |
188 | #define CODA9_CMD_DEC_PIC_ROT_ADDR_CB 0x18c | ||
154 | #define CODA_CMD_DEC_PIC_ROT_STRIDE 0x190 | 189 | #define CODA_CMD_DEC_PIC_ROT_STRIDE 0x190 |
190 | #define CODA9_CMD_DEC_PIC_ROT_ADDR_CR 0x190 | ||
191 | #define CODA9_CMD_DEC_PIC_ROT_STRIDE 0x1b8 | ||
155 | 192 | ||
156 | #define CODA_CMD_DEC_PIC_OPTION 0x194 | 193 | #define CODA_CMD_DEC_PIC_OPTION 0x194 |
157 | #define CODA_PRE_SCAN_EN (1 << 0) | 194 | #define CODA_PRE_SCAN_EN (1 << 0) |
@@ -183,25 +220,39 @@ | |||
183 | #define CODA_RET_DEC_PIC_CROP_TOP_BOTTOM 0x1e4 | 220 | #define CODA_RET_DEC_PIC_CROP_TOP_BOTTOM 0x1e4 |
184 | #define CODA_RET_DEC_PIC_FRAME_NEED 0x1ec | 221 | #define CODA_RET_DEC_PIC_FRAME_NEED 0x1ec |
185 | 222 | ||
223 | #define CODA9_RET_DEC_PIC_VP8_PIC_REPORT 0x1e8 | ||
224 | #define CODA9_RET_DEC_PIC_ASPECT 0x1f0 | ||
225 | #define CODA9_RET_DEC_PIC_VP8_SCALE_INFO 0x1f0 | ||
226 | #define CODA9_RET_DEC_PIC_FRATE_NR 0x1f4 | ||
227 | #define CODA9_RET_DEC_PIC_FRATE_DR 0x1f8 | ||
228 | |||
186 | /* Encoder Sequence Initialization */ | 229 | /* Encoder Sequence Initialization */ |
187 | #define CODA_CMD_ENC_SEQ_BB_START 0x180 | 230 | #define CODA_CMD_ENC_SEQ_BB_START 0x180 |
188 | #define CODA_CMD_ENC_SEQ_BB_SIZE 0x184 | 231 | #define CODA_CMD_ENC_SEQ_BB_SIZE 0x184 |
189 | #define CODA_CMD_ENC_SEQ_OPTION 0x188 | 232 | #define CODA_CMD_ENC_SEQ_OPTION 0x188 |
190 | #define CODA7_OPTION_AVCINTRA16X16ONLY_OFFSET 9 | 233 | #define CODA7_OPTION_AVCINTRA16X16ONLY_OFFSET 9 |
234 | #define CODA9_OPTION_MVC_PREFIX_NAL_OFFSET 9 | ||
191 | #define CODA7_OPTION_GAMMA_OFFSET 8 | 235 | #define CODA7_OPTION_GAMMA_OFFSET 8 |
236 | #define CODA9_OPTION_MVC_PARASET_REFRESH_OFFSET 8 | ||
192 | #define CODA7_OPTION_RCQPMAX_OFFSET 7 | 237 | #define CODA7_OPTION_RCQPMAX_OFFSET 7 |
238 | #define CODA9_OPTION_GAMMA_OFFSET 7 | ||
193 | #define CODADX6_OPTION_GAMMA_OFFSET 7 | 239 | #define CODADX6_OPTION_GAMMA_OFFSET 7 |
194 | #define CODA7_OPTION_RCQPMIN_OFFSET 6 | 240 | #define CODA7_OPTION_RCQPMIN_OFFSET 6 |
241 | #define CODA9_OPTION_RCQPMAX_OFFSET 6 | ||
195 | #define CODA_OPTION_LIMITQP_OFFSET 6 | 242 | #define CODA_OPTION_LIMITQP_OFFSET 6 |
196 | #define CODA_OPTION_RCINTRAQP_OFFSET 5 | 243 | #define CODA_OPTION_RCINTRAQP_OFFSET 5 |
197 | #define CODA_OPTION_FMO_OFFSET 4 | 244 | #define CODA_OPTION_FMO_OFFSET 4 |
245 | #define CODA9_OPTION_MVC_INTERVIEW_OFFSET 4 | ||
198 | #define CODA_OPTION_AVC_AUD_OFFSET 2 | 246 | #define CODA_OPTION_AVC_AUD_OFFSET 2 |
199 | #define CODA_OPTION_SLICEREPORT_OFFSET 1 | 247 | #define CODA_OPTION_SLICEREPORT_OFFSET 1 |
200 | #define CODA_CMD_ENC_SEQ_COD_STD 0x18c | 248 | #define CODA_CMD_ENC_SEQ_COD_STD 0x18c |
201 | #define CODA_STD_MPEG4 0 | 249 | #define CODA_STD_MPEG4 0 |
250 | #define CODA9_STD_H264 0 | ||
202 | #define CODA_STD_H263 1 | 251 | #define CODA_STD_H263 1 |
203 | #define CODA_STD_H264 2 | 252 | #define CODA_STD_H264 2 |
204 | #define CODA_STD_MJPG 3 | 253 | #define CODA_STD_MJPG 3 |
254 | #define CODA9_STD_MPEG4 3 | ||
255 | |||
205 | #define CODA_CMD_ENC_SEQ_SRC_SIZE 0x190 | 256 | #define CODA_CMD_ENC_SEQ_SRC_SIZE 0x190 |
206 | #define CODA7_PICWIDTH_OFFSET 16 | 257 | #define CODA7_PICWIDTH_OFFSET 16 |
207 | #define CODA7_PICWIDTH_MASK 0xffff | 258 | #define CODA7_PICWIDTH_MASK 0xffff |
@@ -268,15 +319,26 @@ | |||
268 | #define CODA7_CMD_ENC_SEQ_SEARCH_BASE 0x1b8 | 319 | #define CODA7_CMD_ENC_SEQ_SEARCH_BASE 0x1b8 |
269 | #define CODA7_CMD_ENC_SEQ_SEARCH_SIZE 0x1bc | 320 | #define CODA7_CMD_ENC_SEQ_SEARCH_SIZE 0x1bc |
270 | #define CODA7_CMD_ENC_SEQ_INTRA_QP 0x1c4 | 321 | #define CODA7_CMD_ENC_SEQ_INTRA_QP 0x1c4 |
271 | #define CODA_CMD_ENC_SEQ_RC_QP_MAX 0x1c8 | 322 | #define CODA_CMD_ENC_SEQ_RC_QP_MIN_MAX 0x1c8 |
323 | #define CODA_QPMIN_OFFSET 8 | ||
324 | #define CODA_QPMIN_MASK 0x3f | ||
272 | #define CODA_QPMAX_OFFSET 0 | 325 | #define CODA_QPMAX_OFFSET 0 |
273 | #define CODA_QPMAX_MASK 0x3f | 326 | #define CODA_QPMAX_MASK 0x3f |
274 | #define CODA_CMD_ENC_SEQ_RC_GAMMA 0x1cc | 327 | #define CODA_CMD_ENC_SEQ_RC_GAMMA 0x1cc |
275 | #define CODA_GAMMA_OFFSET 0 | 328 | #define CODA_GAMMA_OFFSET 0 |
276 | #define CODA_GAMMA_MASK 0xffff | 329 | #define CODA_GAMMA_MASK 0xffff |
330 | #define CODA_CMD_ENC_SEQ_RC_INTERVAL_MODE 0x1d0 | ||
331 | #define CODA9_CMD_ENC_SEQ_INTRA_WEIGHT 0x1d4 | ||
332 | #define CODA9_CMD_ENC_SEQ_ME_OPTION 0x1d8 | ||
277 | #define CODA_RET_ENC_SEQ_SUCCESS 0x1c0 | 333 | #define CODA_RET_ENC_SEQ_SUCCESS 0x1c0 |
278 | 334 | ||
279 | /* Encoder Picture Run */ | 335 | /* Encoder Picture Run */ |
336 | #define CODA9_CMD_ENC_PIC_SRC_INDEX 0x180 | ||
337 | #define CODA9_CMD_ENC_PIC_SRC_STRIDE 0x184 | ||
338 | #define CODA9_CMD_ENC_PIC_SUB_FRAME_SYNC 0x1a4 | ||
339 | #define CODA9_CMD_ENC_PIC_SRC_ADDR_Y 0x1a8 | ||
340 | #define CODA9_CMD_ENC_PIC_SRC_ADDR_CB 0x1ac | ||
341 | #define CODA9_CMD_ENC_PIC_SRC_ADDR_CR 0x1b0 | ||
280 | #define CODA_CMD_ENC_PIC_SRC_ADDR_Y 0x180 | 342 | #define CODA_CMD_ENC_PIC_SRC_ADDR_Y 0x180 |
281 | #define CODA_CMD_ENC_PIC_SRC_ADDR_CB 0x184 | 343 | #define CODA_CMD_ENC_PIC_SRC_ADDR_CB 0x184 |
282 | #define CODA_CMD_ENC_PIC_SRC_ADDR_CR 0x188 | 344 | #define CODA_CMD_ENC_PIC_SRC_ADDR_CR 0x188 |
@@ -291,7 +353,11 @@ | |||
291 | #define CODA_MIR_VER (0x1 << 2) | 353 | #define CODA_MIR_VER (0x1 << 2) |
292 | #define CODA_MIR_HOR (0x2 << 2) | 354 | #define CODA_MIR_HOR (0x2 << 2) |
293 | #define CODA_MIR_VER_HOR (0x3 << 2) | 355 | #define CODA_MIR_VER_HOR (0x3 << 2) |
294 | #define CODA_CMD_ENC_PIC_OPTION 0x194 | 356 | #define CODA_CMD_ENC_PIC_OPTION 0x194 |
357 | #define CODA_FORCE_IPICTURE BIT(1) | ||
358 | #define CODA_REPORT_MB_INFO BIT(3) | ||
359 | #define CODA_REPORT_MV_INFO BIT(4) | ||
360 | #define CODA_REPORT_SLICE_INFO BIT(5) | ||
295 | #define CODA_CMD_ENC_PIC_BB_START 0x198 | 361 | #define CODA_CMD_ENC_PIC_BB_START 0x198 |
296 | #define CODA_CMD_ENC_PIC_BB_SIZE 0x19c | 362 | #define CODA_CMD_ENC_PIC_BB_SIZE 0x19c |
297 | #define CODA_RET_ENC_FRAME_NUM 0x1c0 | 363 | #define CODA_RET_ENC_FRAME_NUM 0x1c0 |
@@ -306,13 +372,30 @@ | |||
306 | #define CODA_CMD_SET_FRAME_BUF_STRIDE 0x184 | 372 | #define CODA_CMD_SET_FRAME_BUF_STRIDE 0x184 |
307 | #define CODA_CMD_SET_FRAME_SLICE_BB_START 0x188 | 373 | #define CODA_CMD_SET_FRAME_SLICE_BB_START 0x188 |
308 | #define CODA_CMD_SET_FRAME_SLICE_BB_SIZE 0x18c | 374 | #define CODA_CMD_SET_FRAME_SLICE_BB_SIZE 0x18c |
375 | #define CODA9_CMD_SET_FRAME_SUBSAMP_A 0x188 | ||
376 | #define CODA9_CMD_SET_FRAME_SUBSAMP_B 0x18c | ||
309 | #define CODA7_CMD_SET_FRAME_AXI_BIT_ADDR 0x190 | 377 | #define CODA7_CMD_SET_FRAME_AXI_BIT_ADDR 0x190 |
310 | #define CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR 0x194 | 378 | #define CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR 0x194 |
311 | #define CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR 0x198 | 379 | #define CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR 0x198 |
312 | #define CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR 0x19c | 380 | #define CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR 0x19c |
313 | #define CODA7_CMD_SET_FRAME_AXI_OVL_ADDR 0x1a0 | 381 | #define CODA7_CMD_SET_FRAME_AXI_OVL_ADDR 0x1a0 |
314 | #define CODA7_CMD_SET_FRAME_MAX_DEC_SIZE 0x1a4 | 382 | #define CODA7_CMD_SET_FRAME_MAX_DEC_SIZE 0x1a4 |
383 | #define CODA9_CMD_SET_FRAME_AXI_BTP_ADDR 0x1a4 | ||
315 | #define CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE 0x1a8 | 384 | #define CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE 0x1a8 |
385 | #define CODA9_CMD_SET_FRAME_CACHE_SIZE 0x1a8 | ||
386 | #define CODA9_CMD_SET_FRAME_CACHE_CONFIG 0x1ac | ||
387 | #define CODA9_CACHE_BYPASS_OFFSET 28 | ||
388 | #define CODA9_CACHE_DUALCONF_OFFSET 26 | ||
389 | #define CODA9_CACHE_PAGEMERGE_OFFSET 24 | ||
390 | #define CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET 16 | ||
391 | #define CODA9_CACHE_CB_BUFFER_SIZE_OFFSET 8 | ||
392 | #define CODA9_CACHE_CR_BUFFER_SIZE_OFFSET 0 | ||
393 | #define CODA9_CMD_SET_FRAME_SUBSAMP_A_MVC 0x1b0 | ||
394 | #define CODA9_CMD_SET_FRAME_SUBSAMP_B_MVC 0x1b4 | ||
395 | #define CODA9_CMD_SET_FRAME_DP_BUF_BASE 0x1b0 | ||
396 | #define CODA9_CMD_SET_FRAME_DP_BUF_SIZE 0x1b4 | ||
397 | #define CODA9_CMD_SET_FRAME_MAX_DEC_SIZE 0x1b8 | ||
398 | #define CODA9_CMD_SET_FRAME_DELAY 0x1bc | ||
316 | 399 | ||
317 | /* Encoder Header */ | 400 | /* Encoder Header */ |
318 | #define CODA_CMD_ENC_HEADER_CODE 0x180 | 401 | #define CODA_CMD_ENC_HEADER_CODE 0x180 |
@@ -322,8 +405,11 @@ | |||
322 | #define CODA_HEADER_MP4V_VOL 0 | 405 | #define CODA_HEADER_MP4V_VOL 0 |
323 | #define CODA_HEADER_MP4V_VOS 1 | 406 | #define CODA_HEADER_MP4V_VOS 1 |
324 | #define CODA_HEADER_MP4V_VIS 2 | 407 | #define CODA_HEADER_MP4V_VIS 2 |
408 | #define CODA9_HEADER_FRAME_CROP (1 << 3) | ||
325 | #define CODA_CMD_ENC_HEADER_BB_START 0x184 | 409 | #define CODA_CMD_ENC_HEADER_BB_START 0x184 |
326 | #define CODA_CMD_ENC_HEADER_BB_SIZE 0x188 | 410 | #define CODA_CMD_ENC_HEADER_BB_SIZE 0x188 |
411 | #define CODA9_CMD_ENC_HEADER_FRAME_CROP_H 0x18c | ||
412 | #define CODA9_CMD_ENC_HEADER_FRAME_CROP_V 0x190 | ||
327 | 413 | ||
328 | /* Get Version */ | 414 | /* Get Version */ |
329 | #define CODA_CMD_FIRMWARE_VERNUM 0x1c0 | 415 | #define CODA_CMD_FIRMWARE_VERNUM 0x1c0 |
@@ -334,5 +420,28 @@ | |||
334 | #define CODA_FIRMWARE_VERNUM(product, major, minor, release) \ | 420 | #define CODA_FIRMWARE_VERNUM(product, major, minor, release) \ |
335 | ((product) << 16 | ((major) << 12) | \ | 421 | ((product) << 16 | ((major) << 12) | \ |
336 | ((minor) << 8) | (release)) | 422 | ((minor) << 8) | (release)) |
423 | #define CODA9_CMD_FIRMWARE_CODE_REV 0x1c4 | ||
424 | |||
425 | #define CODA9_GDMA_BASE 0x1000 | ||
426 | #define CODA9_GDI_WPROT_ERR_CLR (CODA9_GDMA_BASE + 0x0a0) | ||
427 | #define CODA9_GDI_WPROT_RGN_EN (CODA9_GDMA_BASE + 0x0ac) | ||
428 | |||
429 | #define CODA9_GDI_BUS_CTRL (CODA9_GDMA_BASE + 0x0f0) | ||
430 | #define CODA9_GDI_BUS_STATUS (CODA9_GDMA_BASE + 0x0f4) | ||
431 | |||
432 | #define CODA9_GDI_XY2_CAS_0 (CODA9_GDMA_BASE + 0x800) | ||
433 | #define CODA9_GDI_XY2_CAS_F (CODA9_GDMA_BASE + 0x83c) | ||
434 | |||
435 | #define CODA9_GDI_XY2_BA_0 (CODA9_GDMA_BASE + 0x840) | ||
436 | #define CODA9_GDI_XY2_BA_1 (CODA9_GDMA_BASE + 0x844) | ||
437 | #define CODA9_GDI_XY2_BA_2 (CODA9_GDMA_BASE + 0x848) | ||
438 | #define CODA9_GDI_XY2_BA_3 (CODA9_GDMA_BASE + 0x84c) | ||
439 | |||
440 | #define CODA9_GDI_XY2_RAS_0 (CODA9_GDMA_BASE + 0x850) | ||
441 | #define CODA9_GDI_XY2_RAS_F (CODA9_GDMA_BASE + 0x88c) | ||
442 | |||
443 | #define CODA9_GDI_XY2_RBC_CONFIG (CODA9_GDMA_BASE + 0x890) | ||
444 | #define CODA9_GDI_RBC2_AXI_0 (CODA9_GDMA_BASE + 0x8a0) | ||
445 | #define CODA9_GDI_RBC2_AXI_1F (CODA9_GDMA_BASE + 0x91c) | ||
337 | 446 | ||
338 | #endif | 447 | #endif |
diff --git a/drivers/media/platform/davinci/dm644x_ccdc.c b/drivers/media/platform/davinci/dm644x_ccdc.c index 30fa08405d61..07e98df3d867 100644 --- a/drivers/media/platform/davinci/dm644x_ccdc.c +++ b/drivers/media/platform/davinci/dm644x_ccdc.c | |||
@@ -581,13 +581,8 @@ void ccdc_config_raw(void) | |||
581 | config_params->alaw.enable) | 581 | config_params->alaw.enable) |
582 | syn_mode |= CCDC_DATA_PACK_ENABLE; | 582 | syn_mode |= CCDC_DATA_PACK_ENABLE; |
583 | 583 | ||
584 | #ifdef CONFIG_DM644X_VIDEO_PORT_ENABLE | ||
585 | /* enable video port */ | ||
586 | val = CCDC_ENABLE_VIDEO_PORT; | ||
587 | #else | ||
588 | /* disable video port */ | 584 | /* disable video port */ |
589 | val = CCDC_DISABLE_VIDEO_PORT; | 585 | val = CCDC_DISABLE_VIDEO_PORT; |
590 | #endif | ||
591 | 586 | ||
592 | if (config_params->data_sz == CCDC_DATA_8BITS) | 587 | if (config_params->data_sz == CCDC_DATA_8BITS) |
593 | val |= (CCDC_DATA_10BITS & CCDC_FMTCFG_VPIN_MASK) | 588 | val |= (CCDC_DATA_10BITS & CCDC_FMTCFG_VPIN_MASK) |
diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c index bf5eff99452b..73496d953ba0 100644 --- a/drivers/media/platform/davinci/vpbe_display.c +++ b/drivers/media/platform/davinci/vpbe_display.c | |||
@@ -1709,7 +1709,6 @@ static int register_device(struct vpbe_layer *vpbe_display_layer, | |||
1709 | vpbe_display_layer->disp_dev = disp_dev; | 1709 | vpbe_display_layer->disp_dev = disp_dev; |
1710 | /* set the driver data in platform device */ | 1710 | /* set the driver data in platform device */ |
1711 | platform_set_drvdata(pdev, disp_dev); | 1711 | platform_set_drvdata(pdev, disp_dev); |
1712 | set_bit(V4L2_FL_USE_FH_PRIO, &vpbe_display_layer->video_dev.flags); | ||
1713 | video_set_drvdata(&vpbe_display_layer->video_dev, | 1712 | video_set_drvdata(&vpbe_display_layer->video_dev, |
1714 | vpbe_display_layer); | 1713 | vpbe_display_layer); |
1715 | 1714 | ||
diff --git a/drivers/media/platform/davinci/vpfe_capture.c b/drivers/media/platform/davinci/vpfe_capture.c index a51bda2fb637..ea7661a27479 100644 --- a/drivers/media/platform/davinci/vpfe_capture.c +++ b/drivers/media/platform/davinci/vpfe_capture.c | |||
@@ -1916,7 +1916,6 @@ static int vpfe_probe(struct platform_device *pdev) | |||
1916 | v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, | 1916 | v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, |
1917 | "video_dev=%x\n", (int)&vpfe_dev->video_dev); | 1917 | "video_dev=%x\n", (int)&vpfe_dev->video_dev); |
1918 | vpfe_dev->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1918 | vpfe_dev->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
1919 | set_bit(V4L2_FL_USE_FH_PRIO, &vpfe_dev->video_dev->flags); | ||
1920 | ret = video_register_device(vpfe_dev->video_dev, | 1919 | ret = video_register_device(vpfe_dev->video_dev, |
1921 | VFL_TYPE_GRABBER, -1); | 1920 | VFL_TYPE_GRABBER, -1); |
1922 | 1921 | ||
diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index 1e4ec697fb10..b054b7eec53d 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c | |||
@@ -39,32 +39,10 @@ MODULE_VERSION(VPIF_CAPTURE_VERSION); | |||
39 | v4l2_dbg(level, debug, &vpif_obj.v4l2_dev, fmt, ## arg) | 39 | v4l2_dbg(level, debug, &vpif_obj.v4l2_dev, fmt, ## arg) |
40 | 40 | ||
41 | static int debug = 1; | 41 | static int debug = 1; |
42 | static u32 ch0_numbuffers = 3; | ||
43 | static u32 ch1_numbuffers = 3; | ||
44 | static u32 ch0_bufsize = 1920 * 1080 * 2; | ||
45 | static u32 ch1_bufsize = 720 * 576 * 2; | ||
46 | 42 | ||
47 | module_param(debug, int, 0644); | 43 | module_param(debug, int, 0644); |
48 | module_param(ch0_numbuffers, uint, S_IRUGO); | ||
49 | module_param(ch1_numbuffers, uint, S_IRUGO); | ||
50 | module_param(ch0_bufsize, uint, S_IRUGO); | ||
51 | module_param(ch1_bufsize, uint, S_IRUGO); | ||
52 | 44 | ||
53 | MODULE_PARM_DESC(debug, "Debug level 0-1"); | 45 | MODULE_PARM_DESC(debug, "Debug level 0-1"); |
54 | MODULE_PARM_DESC(ch2_numbuffers, "Channel0 buffer count (default:3)"); | ||
55 | MODULE_PARM_DESC(ch3_numbuffers, "Channel1 buffer count (default:3)"); | ||
56 | MODULE_PARM_DESC(ch2_bufsize, "Channel0 buffer size (default:1920 x 1080 x 2)"); | ||
57 | MODULE_PARM_DESC(ch3_bufsize, "Channel1 buffer size (default:720 x 576 x 2)"); | ||
58 | |||
59 | static struct vpif_config_params config_params = { | ||
60 | .min_numbuffers = 3, | ||
61 | .numbuffers[0] = 3, | ||
62 | .numbuffers[1] = 3, | ||
63 | .min_bufsize[0] = 720 * 480 * 2, | ||
64 | .min_bufsize[1] = 720 * 480 * 2, | ||
65 | .channel_bufsize[0] = 1920 * 1080 * 2, | ||
66 | .channel_bufsize[1] = 720 * 576 * 2, | ||
67 | }; | ||
68 | 46 | ||
69 | #define VPIF_DRIVER_NAME "vpif_capture" | 47 | #define VPIF_DRIVER_NAME "vpif_capture" |
70 | 48 | ||
@@ -521,10 +499,28 @@ static int vpif_update_std_info(struct channel_obj *ch) | |||
521 | common->width = std_info->width; | 499 | common->width = std_info->width; |
522 | common->fmt.fmt.pix.height = std_info->height; | 500 | common->fmt.fmt.pix.height = std_info->height; |
523 | common->height = std_info->height; | 501 | common->height = std_info->height; |
502 | common->fmt.fmt.pix.sizeimage = common->height * common->width * 2; | ||
524 | common->fmt.fmt.pix.bytesperline = std_info->width; | 503 | common->fmt.fmt.pix.bytesperline = std_info->width; |
525 | vpifparams->video_params.hpitch = std_info->width; | 504 | vpifparams->video_params.hpitch = std_info->width; |
526 | vpifparams->video_params.storage_mode = std_info->frm_fmt; | 505 | vpifparams->video_params.storage_mode = std_info->frm_fmt; |
527 | 506 | ||
507 | if (vid_ch->stdid) | ||
508 | common->fmt.fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
509 | else | ||
510 | common->fmt.fmt.pix.colorspace = V4L2_COLORSPACE_REC709; | ||
511 | |||
512 | if (ch->vpifparams.std_info.frm_fmt) | ||
513 | common->fmt.fmt.pix.field = V4L2_FIELD_NONE; | ||
514 | else | ||
515 | common->fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; | ||
516 | |||
517 | if (ch->vpifparams.iface.if_type == VPIF_IF_RAW_BAYER) | ||
518 | common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8; | ||
519 | else | ||
520 | common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P; | ||
521 | |||
522 | common->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
523 | |||
528 | return 0; | 524 | return 0; |
529 | } | 525 | } |
530 | 526 | ||
@@ -601,27 +597,6 @@ static void vpif_calculate_offsets(struct channel_obj *ch) | |||
601 | } | 597 | } |
602 | 598 | ||
603 | /** | 599 | /** |
604 | * vpif_config_format: configure default frame format in the device | ||
605 | * ch : ptr to channel object | ||
606 | */ | ||
607 | static void vpif_config_format(struct channel_obj *ch) | ||
608 | { | ||
609 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | ||
610 | |||
611 | vpif_dbg(2, debug, "vpif_config_format\n"); | ||
612 | |||
613 | common->fmt.fmt.pix.field = V4L2_FIELD_ANY; | ||
614 | common->fmt.fmt.pix.sizeimage | ||
615 | = config_params.channel_bufsize[ch->channel_id]; | ||
616 | |||
617 | if (ch->vpifparams.iface.if_type == VPIF_IF_RAW_BAYER) | ||
618 | common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8; | ||
619 | else | ||
620 | common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P; | ||
621 | common->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
622 | } | ||
623 | |||
624 | /** | ||
625 | * vpif_get_default_field() - Get default field type based on interface | 600 | * vpif_get_default_field() - Get default field type based on interface |
626 | * @vpif_params - ptr to vpif params | 601 | * @vpif_params - ptr to vpif params |
627 | */ | 602 | */ |
@@ -633,112 +608,6 @@ static inline enum v4l2_field vpif_get_default_field( | |||
633 | } | 608 | } |
634 | 609 | ||
635 | /** | 610 | /** |
636 | * vpif_check_format() - check given pixel format for compatibility | ||
637 | * @ch - channel ptr | ||
638 | * @pixfmt - Given pixel format | ||
639 | * @update - update the values as per hardware requirement | ||
640 | * | ||
641 | * Check the application pixel format for S_FMT and update the input | ||
642 | * values as per hardware limits for TRY_FMT. The default pixel and | ||
643 | * field format is selected based on interface type. | ||
644 | */ | ||
645 | static int vpif_check_format(struct channel_obj *ch, | ||
646 | struct v4l2_pix_format *pixfmt, | ||
647 | int update) | ||
648 | { | ||
649 | struct common_obj *common = &(ch->common[VPIF_VIDEO_INDEX]); | ||
650 | struct vpif_params *vpif_params = &ch->vpifparams; | ||
651 | enum v4l2_field field = pixfmt->field; | ||
652 | u32 sizeimage, hpitch, vpitch; | ||
653 | int ret = -EINVAL; | ||
654 | |||
655 | vpif_dbg(2, debug, "vpif_check_format\n"); | ||
656 | /** | ||
657 | * first check for the pixel format. If if_type is Raw bayer, | ||
658 | * only V4L2_PIX_FMT_SBGGR8 format is supported. Otherwise only | ||
659 | * V4L2_PIX_FMT_YUV422P is supported | ||
660 | */ | ||
661 | if (vpif_params->iface.if_type == VPIF_IF_RAW_BAYER) { | ||
662 | if (pixfmt->pixelformat != V4L2_PIX_FMT_SBGGR8) { | ||
663 | if (!update) { | ||
664 | vpif_dbg(2, debug, "invalid pix format\n"); | ||
665 | goto exit; | ||
666 | } | ||
667 | pixfmt->pixelformat = V4L2_PIX_FMT_SBGGR8; | ||
668 | } | ||
669 | } else { | ||
670 | if (pixfmt->pixelformat != V4L2_PIX_FMT_YUV422P) { | ||
671 | if (!update) { | ||
672 | vpif_dbg(2, debug, "invalid pixel format\n"); | ||
673 | goto exit; | ||
674 | } | ||
675 | pixfmt->pixelformat = V4L2_PIX_FMT_YUV422P; | ||
676 | } | ||
677 | } | ||
678 | |||
679 | if (!(VPIF_VALID_FIELD(field))) { | ||
680 | if (!update) { | ||
681 | vpif_dbg(2, debug, "invalid field format\n"); | ||
682 | goto exit; | ||
683 | } | ||
684 | /** | ||
685 | * By default use FIELD_NONE for RAW Bayer capture | ||
686 | * and FIELD_INTERLACED for other interfaces | ||
687 | */ | ||
688 | field = vpif_get_default_field(&vpif_params->iface); | ||
689 | } else if (field == V4L2_FIELD_ANY) | ||
690 | /* unsupported field. Use default */ | ||
691 | field = vpif_get_default_field(&vpif_params->iface); | ||
692 | |||
693 | /* validate the hpitch */ | ||
694 | hpitch = pixfmt->bytesperline; | ||
695 | if (hpitch < vpif_params->std_info.width) { | ||
696 | if (!update) { | ||
697 | vpif_dbg(2, debug, "invalid hpitch\n"); | ||
698 | goto exit; | ||
699 | } | ||
700 | hpitch = vpif_params->std_info.width; | ||
701 | } | ||
702 | |||
703 | sizeimage = pixfmt->sizeimage; | ||
704 | |||
705 | vpitch = sizeimage / (hpitch * 2); | ||
706 | |||
707 | /* validate the vpitch */ | ||
708 | if (vpitch < vpif_params->std_info.height) { | ||
709 | if (!update) { | ||
710 | vpif_dbg(2, debug, "Invalid vpitch\n"); | ||
711 | goto exit; | ||
712 | } | ||
713 | vpitch = vpif_params->std_info.height; | ||
714 | } | ||
715 | |||
716 | /* Check for 8 byte alignment */ | ||
717 | if (!ALIGN(hpitch, 8)) { | ||
718 | if (!update) { | ||
719 | vpif_dbg(2, debug, "invalid pitch alignment\n"); | ||
720 | goto exit; | ||
721 | } | ||
722 | /* adjust to next 8 byte boundary */ | ||
723 | hpitch = (((hpitch + 7) / 8) * 8); | ||
724 | } | ||
725 | /* if update is set, modify the bytesperline and sizeimage */ | ||
726 | if (update) { | ||
727 | pixfmt->bytesperline = hpitch; | ||
728 | pixfmt->sizeimage = hpitch * vpitch * 2; | ||
729 | } | ||
730 | /** | ||
731 | * Image width and height is always based on current standard width and | ||
732 | * height | ||
733 | */ | ||
734 | pixfmt->width = common->fmt.fmt.pix.width; | ||
735 | pixfmt->height = common->fmt.fmt.pix.height; | ||
736 | return 0; | ||
737 | exit: | ||
738 | return ret; | ||
739 | } | ||
740 | |||
741 | /** | ||
742 | * vpif_config_addr() - function to configure buffer address in vpif | 611 | * vpif_config_addr() - function to configure buffer address in vpif |
743 | * @ch - channel ptr | 612 | * @ch - channel ptr |
744 | * @muxmode - channel mux mode | 613 | * @muxmode - channel mux mode |
@@ -948,9 +817,6 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id std_id) | |||
948 | return -EINVAL; | 817 | return -EINVAL; |
949 | } | 818 | } |
950 | 819 | ||
951 | /* Configure the default format information */ | ||
952 | vpif_config_format(ch); | ||
953 | |||
954 | /* set standard in the sub device */ | 820 | /* set standard in the sub device */ |
955 | ret = v4l2_subdev_call(ch->sd, video, s_std, std_id); | 821 | ret = v4l2_subdev_call(ch->sd, video, s_std, std_id); |
956 | if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) { | 822 | if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) { |
@@ -977,10 +843,8 @@ static int vpif_enum_input(struct file *file, void *priv, | |||
977 | 843 | ||
978 | chan_cfg = &config->chan_config[ch->channel_id]; | 844 | chan_cfg = &config->chan_config[ch->channel_id]; |
979 | 845 | ||
980 | if (input->index >= chan_cfg->input_count) { | 846 | if (input->index >= chan_cfg->input_count) |
981 | vpif_dbg(1, debug, "Invalid input index\n"); | ||
982 | return -EINVAL; | 847 | return -EINVAL; |
983 | } | ||
984 | 848 | ||
985 | memcpy(input, &chan_cfg->inputs[input->index].input, | 849 | memcpy(input, &chan_cfg->inputs[input->index].input, |
986 | sizeof(*input)); | 850 | sizeof(*input)); |
@@ -1069,8 +933,34 @@ static int vpif_try_fmt_vid_cap(struct file *file, void *priv, | |||
1069 | struct video_device *vdev = video_devdata(file); | 933 | struct video_device *vdev = video_devdata(file); |
1070 | struct channel_obj *ch = video_get_drvdata(vdev); | 934 | struct channel_obj *ch = video_get_drvdata(vdev); |
1071 | struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; | 935 | struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; |
936 | struct common_obj *common = &(ch->common[VPIF_VIDEO_INDEX]); | ||
937 | struct vpif_params *vpif_params = &ch->vpifparams; | ||
1072 | 938 | ||
1073 | return vpif_check_format(ch, pixfmt, 1); | 939 | /* |
940 | * to supress v4l-compliance warnings silently correct | ||
941 | * the pixelformat | ||
942 | */ | ||
943 | if (vpif_params->iface.if_type == VPIF_IF_RAW_BAYER) { | ||
944 | if (pixfmt->pixelformat != V4L2_PIX_FMT_SBGGR8) | ||
945 | pixfmt->pixelformat = V4L2_PIX_FMT_SBGGR8; | ||
946 | } else { | ||
947 | if (pixfmt->pixelformat != V4L2_PIX_FMT_YUV422P) | ||
948 | pixfmt->pixelformat = V4L2_PIX_FMT_YUV422P; | ||
949 | } | ||
950 | |||
951 | common->fmt.fmt.pix.pixelformat = pixfmt->pixelformat; | ||
952 | |||
953 | vpif_update_std_info(ch); | ||
954 | |||
955 | pixfmt->field = common->fmt.fmt.pix.field; | ||
956 | pixfmt->colorspace = common->fmt.fmt.pix.colorspace; | ||
957 | pixfmt->bytesperline = common->fmt.fmt.pix.width; | ||
958 | pixfmt->width = common->fmt.fmt.pix.width; | ||
959 | pixfmt->height = common->fmt.fmt.pix.height; | ||
960 | pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height * 2; | ||
961 | pixfmt->priv = 0; | ||
962 | |||
963 | return 0; | ||
1074 | } | 964 | } |
1075 | 965 | ||
1076 | 966 | ||
@@ -1108,20 +998,17 @@ static int vpif_s_fmt_vid_cap(struct file *file, void *priv, | |||
1108 | struct video_device *vdev = video_devdata(file); | 998 | struct video_device *vdev = video_devdata(file); |
1109 | struct channel_obj *ch = video_get_drvdata(vdev); | 999 | struct channel_obj *ch = video_get_drvdata(vdev); |
1110 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | 1000 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; |
1111 | struct v4l2_pix_format *pixfmt; | 1001 | int ret; |
1112 | int ret = 0; | ||
1113 | 1002 | ||
1114 | vpif_dbg(2, debug, "%s\n", __func__); | 1003 | vpif_dbg(2, debug, "%s\n", __func__); |
1115 | 1004 | ||
1116 | if (vb2_is_busy(&common->buffer_queue)) | 1005 | if (vb2_is_busy(&common->buffer_queue)) |
1117 | return -EBUSY; | 1006 | return -EBUSY; |
1118 | 1007 | ||
1119 | pixfmt = &fmt->fmt.pix; | 1008 | ret = vpif_try_fmt_vid_cap(file, priv, fmt); |
1120 | /* Check for valid field format */ | ||
1121 | ret = vpif_check_format(ch, pixfmt, 0); | ||
1122 | |||
1123 | if (ret) | 1009 | if (ret) |
1124 | return ret; | 1010 | return ret; |
1011 | |||
1125 | /* store the format in the channel object */ | 1012 | /* store the format in the channel object */ |
1126 | common->fmt = *fmt; | 1013 | common->fmt = *fmt; |
1127 | return 0; | 1014 | return 0; |
@@ -1411,36 +1298,9 @@ static struct v4l2_file_operations vpif_fops = { | |||
1411 | */ | 1298 | */ |
1412 | static int initialize_vpif(void) | 1299 | static int initialize_vpif(void) |
1413 | { | 1300 | { |
1414 | int err = 0, i, j; | 1301 | int err, i, j; |
1415 | int free_channel_objects_index; | 1302 | int free_channel_objects_index; |
1416 | 1303 | ||
1417 | /* Default number of buffers should be 3 */ | ||
1418 | if ((ch0_numbuffers > 0) && | ||
1419 | (ch0_numbuffers < config_params.min_numbuffers)) | ||
1420 | ch0_numbuffers = config_params.min_numbuffers; | ||
1421 | if ((ch1_numbuffers > 0) && | ||
1422 | (ch1_numbuffers < config_params.min_numbuffers)) | ||
1423 | ch1_numbuffers = config_params.min_numbuffers; | ||
1424 | |||
1425 | /* Set buffer size to min buffers size if it is invalid */ | ||
1426 | if (ch0_bufsize < config_params.min_bufsize[VPIF_CHANNEL0_VIDEO]) | ||
1427 | ch0_bufsize = | ||
1428 | config_params.min_bufsize[VPIF_CHANNEL0_VIDEO]; | ||
1429 | if (ch1_bufsize < config_params.min_bufsize[VPIF_CHANNEL1_VIDEO]) | ||
1430 | ch1_bufsize = | ||
1431 | config_params.min_bufsize[VPIF_CHANNEL1_VIDEO]; | ||
1432 | |||
1433 | config_params.numbuffers[VPIF_CHANNEL0_VIDEO] = ch0_numbuffers; | ||
1434 | config_params.numbuffers[VPIF_CHANNEL1_VIDEO] = ch1_numbuffers; | ||
1435 | if (ch0_numbuffers) { | ||
1436 | config_params.channel_bufsize[VPIF_CHANNEL0_VIDEO] | ||
1437 | = ch0_bufsize; | ||
1438 | } | ||
1439 | if (ch1_numbuffers) { | ||
1440 | config_params.channel_bufsize[VPIF_CHANNEL1_VIDEO] | ||
1441 | = ch1_bufsize; | ||
1442 | } | ||
1443 | |||
1444 | /* Allocate memory for six channel objects */ | 1304 | /* Allocate memory for six channel objects */ |
1445 | for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) { | 1305 | for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) { |
1446 | vpif_obj.dev[i] = | 1306 | vpif_obj.dev[i] = |
@@ -1496,6 +1356,11 @@ static int vpif_probe_complete(void) | |||
1496 | if (err) | 1356 | if (err) |
1497 | goto probe_out; | 1357 | goto probe_out; |
1498 | 1358 | ||
1359 | /* set initial format */ | ||
1360 | ch->video.stdid = V4L2_STD_525_60; | ||
1361 | memset(&ch->video.dv_timings, 0, sizeof(ch->video.dv_timings)); | ||
1362 | vpif_update_std_info(ch); | ||
1363 | |||
1499 | /* Initialize vb2 queue */ | 1364 | /* Initialize vb2 queue */ |
1500 | q = &common->buffer_queue; | 1365 | q = &common->buffer_queue; |
1501 | q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1366 | q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
@@ -1533,7 +1398,6 @@ static int vpif_probe_complete(void) | |||
1533 | vdev->vfl_dir = VFL_DIR_RX; | 1398 | vdev->vfl_dir = VFL_DIR_RX; |
1534 | vdev->queue = q; | 1399 | vdev->queue = q; |
1535 | vdev->lock = &common->lock; | 1400 | vdev->lock = &common->lock; |
1536 | set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags); | ||
1537 | video_set_drvdata(ch->video_dev, ch); | 1401 | video_set_drvdata(ch->video_dev, ch); |
1538 | err = video_register_device(vdev, | 1402 | err = video_register_device(vdev, |
1539 | VFL_TYPE_GRABBER, (j ? 1 : 0)); | 1403 | VFL_TYPE_GRABBER, (j ? 1 : 0)); |
@@ -1714,7 +1578,7 @@ static int vpif_remove(struct platform_device *device) | |||
1714 | for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) { | 1578 | for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) { |
1715 | /* Get the pointer to the channel object */ | 1579 | /* Get the pointer to the channel object */ |
1716 | ch = vpif_obj.dev[i]; | 1580 | ch = vpif_obj.dev[i]; |
1717 | common = &ch->common[i]; | 1581 | common = &ch->common[VPIF_VIDEO_INDEX]; |
1718 | vb2_dma_contig_cleanup_ctx(common->alloc_ctx); | 1582 | vb2_dma_contig_cleanup_ctx(common->alloc_ctx); |
1719 | /* Unregister video device */ | 1583 | /* Unregister video device */ |
1720 | video_unregister_device(ch->video_dev); | 1584 | video_unregister_device(ch->video_dev); |
diff --git a/drivers/media/platform/davinci/vpif_capture.h b/drivers/media/platform/davinci/vpif_capture.h index 1ee17824f484..f65d28d38e66 100644 --- a/drivers/media/platform/davinci/vpif_capture.h +++ b/drivers/media/platform/davinci/vpif_capture.h | |||
@@ -119,15 +119,4 @@ struct vpif_device { | |||
119 | struct vpif_capture_config *config; | 119 | struct vpif_capture_config *config; |
120 | }; | 120 | }; |
121 | 121 | ||
122 | struct vpif_config_params { | ||
123 | u8 min_numbuffers; | ||
124 | u8 numbuffers[VPIF_CAPTURE_NUM_CHANNELS]; | ||
125 | s8 device_type; | ||
126 | u32 min_bufsize[VPIF_CAPTURE_NUM_CHANNELS]; | ||
127 | u32 channel_bufsize[VPIF_CAPTURE_NUM_CHANNELS]; | ||
128 | u8 default_device[VPIF_CAPTURE_NUM_CHANNELS]; | ||
129 | u32 video_limit[VPIF_CAPTURE_NUM_CHANNELS]; | ||
130 | u8 max_device_type; | ||
131 | }; | ||
132 | |||
133 | #endif /* VPIF_CAPTURE_H */ | 122 | #endif /* VPIF_CAPTURE_H */ |
diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index b431b58f39e3..a03ec7381cfe 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c | |||
@@ -649,7 +649,6 @@ static int vpif_try_fmt_vid_out(struct file *file, void *priv, | |||
649 | pixfmt->width = common->fmt.fmt.pix.width; | 649 | pixfmt->width = common->fmt.fmt.pix.width; |
650 | pixfmt->height = common->fmt.fmt.pix.height; | 650 | pixfmt->height = common->fmt.fmt.pix.height; |
651 | pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height * 2; | 651 | pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height * 2; |
652 | pixfmt->priv = 0; | ||
653 | 652 | ||
654 | return 0; | 653 | return 0; |
655 | } | 654 | } |
@@ -1224,7 +1223,6 @@ static int vpif_probe_complete(void) | |||
1224 | vdev->vfl_dir = VFL_DIR_TX; | 1223 | vdev->vfl_dir = VFL_DIR_TX; |
1225 | vdev->queue = q; | 1224 | vdev->queue = q; |
1226 | vdev->lock = &common->lock; | 1225 | vdev->lock = &common->lock; |
1227 | set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags); | ||
1228 | video_set_drvdata(ch->video_dev, ch); | 1226 | video_set_drvdata(ch->video_dev, ch); |
1229 | err = video_register_device(vdev, VFL_TYPE_GRABBER, | 1227 | err = video_register_device(vdev, VFL_TYPE_GRABBER, |
1230 | (j ? 3 : 2)); | 1228 | (j ? 3 : 2)); |
@@ -1388,7 +1386,7 @@ static int vpif_remove(struct platform_device *device) | |||
1388 | for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) { | 1386 | for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) { |
1389 | /* Get the pointer to the channel object */ | 1387 | /* Get the pointer to the channel object */ |
1390 | ch = vpif_obj.dev[i]; | 1388 | ch = vpif_obj.dev[i]; |
1391 | common = &ch->common[i]; | 1389 | common = &ch->common[VPIF_VIDEO_INDEX]; |
1392 | vb2_dma_contig_cleanup_ctx(common->alloc_ctx); | 1390 | vb2_dma_contig_cleanup_ctx(common->alloc_ctx); |
1393 | /* Unregister video device */ | 1391 | /* Unregister video device */ |
1394 | video_unregister_device(ch->video_dev); | 1392 | video_unregister_device(ch->video_dev); |
diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c index c21d14fd61db..d36c507a0ba2 100644 --- a/drivers/media/platform/m2m-deinterlace.c +++ b/drivers/media/platform/m2m-deinterlace.c | |||
@@ -1002,7 +1002,7 @@ static int deinterlace_probe(struct platform_device *pdev) | |||
1002 | dma_cap_mask_t mask; | 1002 | dma_cap_mask_t mask; |
1003 | int ret = 0; | 1003 | int ret = 0; |
1004 | 1004 | ||
1005 | pcdev = kzalloc(sizeof *pcdev, GFP_KERNEL); | 1005 | pcdev = devm_kzalloc(&pdev->dev, sizeof(*pcdev), GFP_KERNEL); |
1006 | if (!pcdev) | 1006 | if (!pcdev) |
1007 | return -ENOMEM; | 1007 | return -ENOMEM; |
1008 | 1008 | ||
@@ -1012,7 +1012,7 @@ static int deinterlace_probe(struct platform_device *pdev) | |||
1012 | dma_cap_set(DMA_INTERLEAVE, mask); | 1012 | dma_cap_set(DMA_INTERLEAVE, mask); |
1013 | pcdev->dma_chan = dma_request_channel(mask, NULL, pcdev); | 1013 | pcdev->dma_chan = dma_request_channel(mask, NULL, pcdev); |
1014 | if (!pcdev->dma_chan) | 1014 | if (!pcdev->dma_chan) |
1015 | goto free_dev; | 1015 | return -ENODEV; |
1016 | 1016 | ||
1017 | if (!dma_has_cap(DMA_INTERLEAVE, pcdev->dma_chan->device->cap_mask)) { | 1017 | if (!dma_has_cap(DMA_INTERLEAVE, pcdev->dma_chan->device->cap_mask)) { |
1018 | v4l2_err(&pcdev->v4l2_dev, "DMA does not support INTERLEAVE\n"); | 1018 | v4l2_err(&pcdev->v4l2_dev, "DMA does not support INTERLEAVE\n"); |
@@ -1078,8 +1078,6 @@ unreg_dev: | |||
1078 | v4l2_device_unregister(&pcdev->v4l2_dev); | 1078 | v4l2_device_unregister(&pcdev->v4l2_dev); |
1079 | rel_dma: | 1079 | rel_dma: |
1080 | dma_release_channel(pcdev->dma_chan); | 1080 | dma_release_channel(pcdev->dma_chan); |
1081 | free_dev: | ||
1082 | kfree(pcdev); | ||
1083 | 1081 | ||
1084 | return ret; | 1082 | return ret; |
1085 | } | 1083 | } |
@@ -1094,7 +1092,6 @@ static int deinterlace_remove(struct platform_device *pdev) | |||
1094 | v4l2_device_unregister(&pcdev->v4l2_dev); | 1092 | v4l2_device_unregister(&pcdev->v4l2_dev); |
1095 | vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); | 1093 | vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); |
1096 | dma_release_channel(pcdev->dma_chan); | 1094 | dma_release_channel(pcdev->dma_chan); |
1097 | kfree(pcdev); | ||
1098 | 1095 | ||
1099 | return 0; | 1096 | return 0; |
1100 | } | 1097 | } |
diff --git a/drivers/media/platform/mem2mem_testdev.c b/drivers/media/platform/mem2mem_testdev.c index 0714070ed7fa..c1b03cfd6ded 100644 --- a/drivers/media/platform/mem2mem_testdev.c +++ b/drivers/media/platform/mem2mem_testdev.c | |||
@@ -532,7 +532,6 @@ static int vidioc_try_fmt(struct v4l2_format *f, struct m2mtest_fmt *fmt) | |||
532 | f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; | 532 | f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; |
533 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | 533 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; |
534 | f->fmt.pix.field = V4L2_FIELD_NONE; | 534 | f->fmt.pix.field = V4L2_FIELD_NONE; |
535 | f->fmt.pix.priv = 0; | ||
536 | 535 | ||
537 | return 0; | 536 | return 0; |
538 | } | 537 | } |
diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c index 9a726eacb29b..2d177fa58471 100644 --- a/drivers/media/platform/omap/omap_vout.c +++ b/drivers/media/platform/omap/omap_vout.c | |||
@@ -165,7 +165,6 @@ static int omap_vout_try_format(struct v4l2_pix_format *pix) | |||
165 | 165 | ||
166 | pix->pixelformat = omap_formats[ifmt].pixelformat; | 166 | pix->pixelformat = omap_formats[ifmt].pixelformat; |
167 | pix->field = V4L2_FIELD_ANY; | 167 | pix->field = V4L2_FIELD_ANY; |
168 | pix->priv = 0; | ||
169 | 168 | ||
170 | switch (pix->pixelformat) { | 169 | switch (pix->pixelformat) { |
171 | case V4L2_PIX_FMT_YUYV: | 170 | case V4L2_PIX_FMT_YUYV: |
@@ -1896,7 +1895,6 @@ static int __init omap_vout_setup_video_data(struct omap_vout_device *vout) | |||
1896 | pix->field = V4L2_FIELD_ANY; | 1895 | pix->field = V4L2_FIELD_ANY; |
1897 | pix->bytesperline = pix->width * 2; | 1896 | pix->bytesperline = pix->width * 2; |
1898 | pix->sizeimage = pix->bytesperline * pix->height; | 1897 | pix->sizeimage = pix->bytesperline * pix->height; |
1899 | pix->priv = 0; | ||
1900 | pix->colorspace = V4L2_COLORSPACE_JPEG; | 1898 | pix->colorspace = V4L2_COLORSPACE_JPEG; |
1901 | 1899 | ||
1902 | vout->bpp = RGB565_BPP; | 1900 | vout->bpp = RGB565_BPP; |
diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c index deba425e3d8f..f33641384e15 100644 --- a/drivers/media/platform/s3c-camif/camif-capture.c +++ b/drivers/media/platform/s3c-camif/camif-capture.c | |||
@@ -1172,7 +1172,6 @@ int s3c_camif_register_video_node(struct camif_dev *camif, int idx) | |||
1172 | goto err_vd_rel; | 1172 | goto err_vd_rel; |
1173 | 1173 | ||
1174 | video_set_drvdata(vfd, vp); | 1174 | video_set_drvdata(vfd, vp); |
1175 | set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags); | ||
1176 | 1175 | ||
1177 | v4l2_ctrl_handler_init(&vp->ctrl_handler, 1); | 1176 | v4l2_ctrl_handler_init(&vp->ctrl_handler, 1); |
1178 | ctrl = v4l2_ctrl_new_std(&vp->ctrl_handler, &s3c_camif_video_ctrl_ops, | 1177 | ctrl = v4l2_ctrl_new_std(&vp->ctrl_handler, &s3c_camif_video_ctrl_ops, |
@@ -1271,6 +1270,7 @@ static int s3c_camif_subdev_get_fmt(struct v4l2_subdev *sd, | |||
1271 | } | 1270 | } |
1272 | 1271 | ||
1273 | mutex_unlock(&camif->lock); | 1272 | mutex_unlock(&camif->lock); |
1273 | mf->field = V4L2_FIELD_NONE; | ||
1274 | mf->colorspace = V4L2_COLORSPACE_JPEG; | 1274 | mf->colorspace = V4L2_COLORSPACE_JPEG; |
1275 | return 0; | 1275 | return 0; |
1276 | } | 1276 | } |
@@ -1319,6 +1319,7 @@ static int s3c_camif_subdev_set_fmt(struct v4l2_subdev *sd, | |||
1319 | v4l2_dbg(1, debug, sd, "pad%d: code: 0x%x, %ux%u\n", | 1319 | v4l2_dbg(1, debug, sd, "pad%d: code: 0x%x, %ux%u\n", |
1320 | fmt->pad, mf->code, mf->width, mf->height); | 1320 | fmt->pad, mf->code, mf->width, mf->height); |
1321 | 1321 | ||
1322 | mf->field = V4L2_FIELD_NONE; | ||
1322 | mf->colorspace = V4L2_COLORSPACE_JPEG; | 1323 | mf->colorspace = V4L2_COLORSPACE_JPEG; |
1323 | mutex_lock(&camif->lock); | 1324 | mutex_lock(&camif->lock); |
1324 | 1325 | ||
diff --git a/drivers/media/platform/s5p-jpeg/Makefile b/drivers/media/platform/s5p-jpeg/Makefile index a1a9169254c3..9e5f214c4667 100644 --- a/drivers/media/platform/s5p-jpeg/Makefile +++ b/drivers/media/platform/s5p-jpeg/Makefile | |||
@@ -1,2 +1,2 @@ | |||
1 | s5p-jpeg-objs := jpeg-core.o jpeg-hw-exynos4.o jpeg-hw-s5p.o | 1 | s5p-jpeg-objs := jpeg-core.o jpeg-hw-exynos3250.o jpeg-hw-exynos4.o jpeg-hw-s5p.o |
2 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG) += s5p-jpeg.o | 2 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG) += s5p-jpeg.o |
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 0dcb796ecad9..e66acbc2a82d 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* linux/drivers/media/platform/s5p-jpeg/jpeg-core.c | 1 | /* linux/drivers/media/platform/s5p-jpeg/jpeg-core.c |
2 | * | 2 | * |
3 | * Copyright (c) 2011-2013 Samsung Electronics Co., Ltd. | 3 | * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd. |
4 | * http://www.samsung.com | 4 | * http://www.samsung.com |
5 | * | 5 | * |
6 | * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> | 6 | * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> |
@@ -32,6 +32,7 @@ | |||
32 | #include "jpeg-core.h" | 32 | #include "jpeg-core.h" |
33 | #include "jpeg-hw-s5p.h" | 33 | #include "jpeg-hw-s5p.h" |
34 | #include "jpeg-hw-exynos4.h" | 34 | #include "jpeg-hw-exynos4.h" |
35 | #include "jpeg-hw-exynos3250.h" | ||
35 | #include "jpeg-regs.h" | 36 | #include "jpeg-regs.h" |
36 | 37 | ||
37 | static struct s5p_jpeg_fmt sjpeg_formats[] = { | 38 | static struct s5p_jpeg_fmt sjpeg_formats[] = { |
@@ -41,6 +42,7 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { | |||
41 | .flags = SJPEG_FMT_FLAG_ENC_CAPTURE | | 42 | .flags = SJPEG_FMT_FLAG_ENC_CAPTURE | |
42 | SJPEG_FMT_FLAG_DEC_OUTPUT | | 43 | SJPEG_FMT_FLAG_DEC_OUTPUT | |
43 | SJPEG_FMT_FLAG_S5P | | 44 | SJPEG_FMT_FLAG_S5P | |
45 | SJPEG_FMT_FLAG_EXYNOS3250 | | ||
44 | SJPEG_FMT_FLAG_EXYNOS4, | 46 | SJPEG_FMT_FLAG_EXYNOS4, |
45 | }, | 47 | }, |
46 | { | 48 | { |
@@ -70,6 +72,19 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { | |||
70 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422, | 72 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422, |
71 | }, | 73 | }, |
72 | { | 74 | { |
75 | .name = "YUV 4:2:2 packed, YCbYCr", | ||
76 | .fourcc = V4L2_PIX_FMT_YUYV, | ||
77 | .depth = 16, | ||
78 | .colplanes = 1, | ||
79 | .h_align = 2, | ||
80 | .v_align = 0, | ||
81 | .flags = SJPEG_FMT_FLAG_ENC_OUTPUT | | ||
82 | SJPEG_FMT_FLAG_DEC_CAPTURE | | ||
83 | SJPEG_FMT_FLAG_EXYNOS3250 | | ||
84 | SJPEG_FMT_NON_RGB, | ||
85 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422, | ||
86 | }, | ||
87 | { | ||
73 | .name = "YUV 4:2:2 packed, YCrYCb", | 88 | .name = "YUV 4:2:2 packed, YCrYCb", |
74 | .fourcc = V4L2_PIX_FMT_YVYU, | 89 | .fourcc = V4L2_PIX_FMT_YVYU, |
75 | .depth = 16, | 90 | .depth = 16, |
@@ -83,6 +98,45 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { | |||
83 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422, | 98 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422, |
84 | }, | 99 | }, |
85 | { | 100 | { |
101 | .name = "YUV 4:2:2 packed, YCrYCb", | ||
102 | .fourcc = V4L2_PIX_FMT_YVYU, | ||
103 | .depth = 16, | ||
104 | .colplanes = 1, | ||
105 | .h_align = 2, | ||
106 | .v_align = 0, | ||
107 | .flags = SJPEG_FMT_FLAG_ENC_OUTPUT | | ||
108 | SJPEG_FMT_FLAG_DEC_CAPTURE | | ||
109 | SJPEG_FMT_FLAG_EXYNOS3250 | | ||
110 | SJPEG_FMT_NON_RGB, | ||
111 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422, | ||
112 | }, | ||
113 | { | ||
114 | .name = "YUV 4:2:2 packed, YCrYCb", | ||
115 | .fourcc = V4L2_PIX_FMT_UYVY, | ||
116 | .depth = 16, | ||
117 | .colplanes = 1, | ||
118 | .h_align = 2, | ||
119 | .v_align = 0, | ||
120 | .flags = SJPEG_FMT_FLAG_ENC_OUTPUT | | ||
121 | SJPEG_FMT_FLAG_DEC_CAPTURE | | ||
122 | SJPEG_FMT_FLAG_EXYNOS3250 | | ||
123 | SJPEG_FMT_NON_RGB, | ||
124 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422, | ||
125 | }, | ||
126 | { | ||
127 | .name = "YUV 4:2:2 packed, YCrYCb", | ||
128 | .fourcc = V4L2_PIX_FMT_VYUY, | ||
129 | .depth = 16, | ||
130 | .colplanes = 1, | ||
131 | .h_align = 2, | ||
132 | .v_align = 0, | ||
133 | .flags = SJPEG_FMT_FLAG_ENC_OUTPUT | | ||
134 | SJPEG_FMT_FLAG_DEC_CAPTURE | | ||
135 | SJPEG_FMT_FLAG_EXYNOS3250 | | ||
136 | SJPEG_FMT_NON_RGB, | ||
137 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422, | ||
138 | }, | ||
139 | { | ||
86 | .name = "RGB565", | 140 | .name = "RGB565", |
87 | .fourcc = V4L2_PIX_FMT_RGB565, | 141 | .fourcc = V4L2_PIX_FMT_RGB565, |
88 | .depth = 16, | 142 | .depth = 16, |
@@ -100,6 +154,32 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { | |||
100 | .fourcc = V4L2_PIX_FMT_RGB565, | 154 | .fourcc = V4L2_PIX_FMT_RGB565, |
101 | .depth = 16, | 155 | .depth = 16, |
102 | .colplanes = 1, | 156 | .colplanes = 1, |
157 | .h_align = 2, | ||
158 | .v_align = 0, | ||
159 | .flags = SJPEG_FMT_FLAG_ENC_OUTPUT | | ||
160 | SJPEG_FMT_FLAG_DEC_CAPTURE | | ||
161 | SJPEG_FMT_FLAG_EXYNOS3250 | | ||
162 | SJPEG_FMT_RGB, | ||
163 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444, | ||
164 | }, | ||
165 | { | ||
166 | .name = "RGB565X", | ||
167 | .fourcc = V4L2_PIX_FMT_RGB565X, | ||
168 | .depth = 16, | ||
169 | .colplanes = 1, | ||
170 | .h_align = 2, | ||
171 | .v_align = 0, | ||
172 | .flags = SJPEG_FMT_FLAG_ENC_OUTPUT | | ||
173 | SJPEG_FMT_FLAG_DEC_CAPTURE | | ||
174 | SJPEG_FMT_FLAG_EXYNOS3250 | | ||
175 | SJPEG_FMT_RGB, | ||
176 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444, | ||
177 | }, | ||
178 | { | ||
179 | .name = "RGB565", | ||
180 | .fourcc = V4L2_PIX_FMT_RGB565, | ||
181 | .depth = 16, | ||
182 | .colplanes = 1, | ||
103 | .h_align = 0, | 183 | .h_align = 0, |
104 | .v_align = 0, | 184 | .v_align = 0, |
105 | .flags = SJPEG_FMT_FLAG_ENC_OUTPUT | | 185 | .flags = SJPEG_FMT_FLAG_ENC_OUTPUT | |
@@ -121,6 +201,19 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { | |||
121 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444, | 201 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444, |
122 | }, | 202 | }, |
123 | { | 203 | { |
204 | .name = "ARGB8888, 32 bpp", | ||
205 | .fourcc = V4L2_PIX_FMT_RGB32, | ||
206 | .depth = 32, | ||
207 | .colplanes = 1, | ||
208 | .h_align = 2, | ||
209 | .v_align = 0, | ||
210 | .flags = SJPEG_FMT_FLAG_ENC_OUTPUT | | ||
211 | SJPEG_FMT_FLAG_DEC_CAPTURE | | ||
212 | SJPEG_FMT_FLAG_EXYNOS3250 | | ||
213 | SJPEG_FMT_RGB, | ||
214 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444, | ||
215 | }, | ||
216 | { | ||
124 | .name = "YUV 4:4:4 planar, Y/CbCr", | 217 | .name = "YUV 4:4:4 planar, Y/CbCr", |
125 | .fourcc = V4L2_PIX_FMT_NV24, | 218 | .fourcc = V4L2_PIX_FMT_NV24, |
126 | .depth = 24, | 219 | .depth = 24, |
@@ -190,9 +283,23 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { | |||
190 | .fourcc = V4L2_PIX_FMT_NV12, | 283 | .fourcc = V4L2_PIX_FMT_NV12, |
191 | .depth = 12, | 284 | .depth = 12, |
192 | .colplanes = 2, | 285 | .colplanes = 2, |
286 | .h_align = 3, | ||
287 | .v_align = 3, | ||
288 | .flags = SJPEG_FMT_FLAG_ENC_OUTPUT | | ||
289 | SJPEG_FMT_FLAG_DEC_CAPTURE | | ||
290 | SJPEG_FMT_FLAG_EXYNOS3250 | | ||
291 | SJPEG_FMT_NON_RGB, | ||
292 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420, | ||
293 | }, | ||
294 | { | ||
295 | .name = "YUV 4:2:0 planar, Y/CbCr", | ||
296 | .fourcc = V4L2_PIX_FMT_NV12, | ||
297 | .depth = 12, | ||
298 | .colplanes = 2, | ||
193 | .h_align = 4, | 299 | .h_align = 4, |
194 | .v_align = 4, | 300 | .v_align = 4, |
195 | .flags = SJPEG_FMT_FLAG_DEC_CAPTURE | | 301 | .flags = SJPEG_FMT_FLAG_ENC_OUTPUT | |
302 | SJPEG_FMT_FLAG_DEC_CAPTURE | | ||
196 | SJPEG_FMT_FLAG_S5P | | 303 | SJPEG_FMT_FLAG_S5P | |
197 | SJPEG_FMT_NON_RGB, | 304 | SJPEG_FMT_NON_RGB, |
198 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420, | 305 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420, |
@@ -202,10 +309,24 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { | |||
202 | .fourcc = V4L2_PIX_FMT_NV21, | 309 | .fourcc = V4L2_PIX_FMT_NV21, |
203 | .depth = 12, | 310 | .depth = 12, |
204 | .colplanes = 2, | 311 | .colplanes = 2, |
312 | .h_align = 3, | ||
313 | .v_align = 3, | ||
314 | .flags = SJPEG_FMT_FLAG_ENC_OUTPUT | | ||
315 | SJPEG_FMT_FLAG_DEC_CAPTURE | | ||
316 | SJPEG_FMT_FLAG_EXYNOS3250 | | ||
317 | SJPEG_FMT_NON_RGB, | ||
318 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420, | ||
319 | }, | ||
320 | { | ||
321 | .name = "YUV 4:2:0 planar, Y/CrCb", | ||
322 | .fourcc = V4L2_PIX_FMT_NV21, | ||
323 | .depth = 12, | ||
324 | .colplanes = 2, | ||
205 | .h_align = 1, | 325 | .h_align = 1, |
206 | .v_align = 1, | 326 | .v_align = 1, |
207 | .flags = SJPEG_FMT_FLAG_ENC_OUTPUT | | 327 | .flags = SJPEG_FMT_FLAG_ENC_OUTPUT | |
208 | SJPEG_FMT_FLAG_DEC_CAPTURE | | 328 | SJPEG_FMT_FLAG_DEC_CAPTURE | |
329 | SJPEG_FMT_FLAG_EXYNOS3250 | | ||
209 | SJPEG_FMT_FLAG_EXYNOS4 | | 330 | SJPEG_FMT_FLAG_EXYNOS4 | |
210 | SJPEG_FMT_NON_RGB, | 331 | SJPEG_FMT_NON_RGB, |
211 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420, | 332 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420, |
@@ -224,6 +345,19 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { | |||
224 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420, | 345 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420, |
225 | }, | 346 | }, |
226 | { | 347 | { |
348 | .name = "YUV 4:2:0 contiguous 3-planar, Y/Cb/Cr", | ||
349 | .fourcc = V4L2_PIX_FMT_YUV420, | ||
350 | .depth = 12, | ||
351 | .colplanes = 3, | ||
352 | .h_align = 4, | ||
353 | .v_align = 4, | ||
354 | .flags = SJPEG_FMT_FLAG_ENC_OUTPUT | | ||
355 | SJPEG_FMT_FLAG_DEC_CAPTURE | | ||
356 | SJPEG_FMT_FLAG_EXYNOS3250 | | ||
357 | SJPEG_FMT_NON_RGB, | ||
358 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420, | ||
359 | }, | ||
360 | { | ||
227 | .name = "Gray", | 361 | .name = "Gray", |
228 | .fourcc = V4L2_PIX_FMT_GREY, | 362 | .fourcc = V4L2_PIX_FMT_GREY, |
229 | .depth = 8, | 363 | .depth = 8, |
@@ -457,6 +591,16 @@ static int exynos4x12_decoded_subsampling[] = { | |||
457 | V4L2_JPEG_CHROMA_SUBSAMPLING_420, | 591 | V4L2_JPEG_CHROMA_SUBSAMPLING_420, |
458 | }; | 592 | }; |
459 | 593 | ||
594 | static int exynos3250_decoded_subsampling[] = { | ||
595 | V4L2_JPEG_CHROMA_SUBSAMPLING_444, | ||
596 | V4L2_JPEG_CHROMA_SUBSAMPLING_422, | ||
597 | V4L2_JPEG_CHROMA_SUBSAMPLING_420, | ||
598 | V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY, | ||
599 | -1, | ||
600 | -1, | ||
601 | V4L2_JPEG_CHROMA_SUBSAMPLING_411, | ||
602 | }; | ||
603 | |||
460 | static inline struct s5p_jpeg_ctx *ctrl_to_ctx(struct v4l2_ctrl *c) | 604 | static inline struct s5p_jpeg_ctx *ctrl_to_ctx(struct v4l2_ctrl *c) |
461 | { | 605 | { |
462 | return container_of(c->handler, struct s5p_jpeg_ctx, ctrl_handler); | 606 | return container_of(c->handler, struct s5p_jpeg_ctx, ctrl_handler); |
@@ -471,14 +615,21 @@ static int s5p_jpeg_to_user_subsampling(struct s5p_jpeg_ctx *ctx) | |||
471 | { | 615 | { |
472 | WARN_ON(ctx->subsampling > 3); | 616 | WARN_ON(ctx->subsampling > 3); |
473 | 617 | ||
474 | if (ctx->jpeg->variant->version == SJPEG_S5P) { | 618 | switch (ctx->jpeg->variant->version) { |
619 | case SJPEG_S5P: | ||
475 | if (ctx->subsampling > 2) | 620 | if (ctx->subsampling > 2) |
476 | return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY; | 621 | return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY; |
477 | return ctx->subsampling; | 622 | return ctx->subsampling; |
478 | } else { | 623 | case SJPEG_EXYNOS3250: |
624 | if (ctx->subsampling > 3) | ||
625 | return V4L2_JPEG_CHROMA_SUBSAMPLING_411; | ||
626 | return exynos3250_decoded_subsampling[ctx->subsampling]; | ||
627 | case SJPEG_EXYNOS4: | ||
479 | if (ctx->subsampling > 2) | 628 | if (ctx->subsampling > 2) |
480 | return V4L2_JPEG_CHROMA_SUBSAMPLING_420; | 629 | return V4L2_JPEG_CHROMA_SUBSAMPLING_420; |
481 | return exynos4x12_decoded_subsampling[ctx->subsampling]; | 630 | return exynos4x12_decoded_subsampling[ctx->subsampling]; |
631 | default: | ||
632 | return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY; | ||
482 | } | 633 | } |
483 | } | 634 | } |
484 | 635 | ||
@@ -646,6 +797,7 @@ static int s5p_jpeg_open(struct file *file) | |||
646 | FMT_TYPE_OUTPUT); | 797 | FMT_TYPE_OUTPUT); |
647 | cap_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_YUYV, | 798 | cap_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_YUYV, |
648 | FMT_TYPE_CAPTURE); | 799 | FMT_TYPE_CAPTURE); |
800 | ctx->scale_factor = EXYNOS3250_DEC_SCALE_FACTOR_8_8; | ||
649 | } | 801 | } |
650 | 802 | ||
651 | ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(jpeg->m2m_dev, ctx, queue_init); | 803 | ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(jpeg->m2m_dev, ctx, queue_init); |
@@ -754,14 +906,14 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result, | |||
754 | while (notfound) { | 906 | while (notfound) { |
755 | c = get_byte(&jpeg_buffer); | 907 | c = get_byte(&jpeg_buffer); |
756 | if (c == -1) | 908 | if (c == -1) |
757 | break; | 909 | return false; |
758 | if (c != 0xff) | 910 | if (c != 0xff) |
759 | continue; | 911 | continue; |
760 | do | 912 | do |
761 | c = get_byte(&jpeg_buffer); | 913 | c = get_byte(&jpeg_buffer); |
762 | while (c == 0xff); | 914 | while (c == 0xff); |
763 | if (c == -1) | 915 | if (c == -1) |
764 | break; | 916 | return false; |
765 | if (c == 0) | 917 | if (c == 0) |
766 | continue; | 918 | continue; |
767 | length = 0; | 919 | length = 0; |
@@ -981,7 +1133,8 @@ static struct s5p_jpeg_fmt *s5p_jpeg_find_format(struct s5p_jpeg_ctx *ctx, | |||
981 | return NULL; | 1133 | return NULL; |
982 | } | 1134 | } |
983 | 1135 | ||
984 | static void jpeg_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax, | 1136 | static void jpeg_bound_align_image(struct s5p_jpeg_ctx *ctx, |
1137 | u32 *w, unsigned int wmin, unsigned int wmax, | ||
985 | unsigned int walign, | 1138 | unsigned int walign, |
986 | u32 *h, unsigned int hmin, unsigned int hmax, | 1139 | u32 *h, unsigned int hmin, unsigned int hmax, |
987 | unsigned int halign) | 1140 | unsigned int halign) |
@@ -993,13 +1146,27 @@ static void jpeg_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax, | |||
993 | 1146 | ||
994 | w_step = 1 << walign; | 1147 | w_step = 1 << walign; |
995 | h_step = 1 << halign; | 1148 | h_step = 1 << halign; |
1149 | |||
1150 | if (ctx->jpeg->variant->version == SJPEG_EXYNOS3250) { | ||
1151 | /* | ||
1152 | * Rightmost and bottommost pixels are cropped by the | ||
1153 | * Exynos3250 JPEG IP for RGB formats, for the specific | ||
1154 | * width and height values respectively. This assignment | ||
1155 | * will result in v4l_bound_align_image returning dimensions | ||
1156 | * reduced by 1 for the aforementioned cases. | ||
1157 | */ | ||
1158 | if (w_step == 4 && ((width & 3) == 1)) { | ||
1159 | wmax = width; | ||
1160 | hmax = height; | ||
1161 | } | ||
1162 | } | ||
1163 | |||
996 | v4l_bound_align_image(w, wmin, wmax, walign, h, hmin, hmax, halign, 0); | 1164 | v4l_bound_align_image(w, wmin, wmax, walign, h, hmin, hmax, halign, 0); |
997 | 1165 | ||
998 | if (*w < width && (*w + w_step) < wmax) | 1166 | if (*w < width && (*w + w_step) < wmax) |
999 | *w += w_step; | 1167 | *w += w_step; |
1000 | if (*h < height && (*h + h_step) < hmax) | 1168 | if (*h < height && (*h + h_step) < hmax) |
1001 | *h += h_step; | 1169 | *h += h_step; |
1002 | |||
1003 | } | 1170 | } |
1004 | 1171 | ||
1005 | static int vidioc_try_fmt(struct v4l2_format *f, struct s5p_jpeg_fmt *fmt, | 1172 | static int vidioc_try_fmt(struct v4l2_format *f, struct s5p_jpeg_fmt *fmt, |
@@ -1015,12 +1182,12 @@ static int vidioc_try_fmt(struct v4l2_format *f, struct s5p_jpeg_fmt *fmt, | |||
1015 | /* V4L2 specification suggests the driver corrects the format struct | 1182 | /* V4L2 specification suggests the driver corrects the format struct |
1016 | * if any of the dimensions is unsupported */ | 1183 | * if any of the dimensions is unsupported */ |
1017 | if (q_type == FMT_TYPE_OUTPUT) | 1184 | if (q_type == FMT_TYPE_OUTPUT) |
1018 | jpeg_bound_align_image(&pix->width, S5P_JPEG_MIN_WIDTH, | 1185 | jpeg_bound_align_image(ctx, &pix->width, S5P_JPEG_MIN_WIDTH, |
1019 | S5P_JPEG_MAX_WIDTH, 0, | 1186 | S5P_JPEG_MAX_WIDTH, 0, |
1020 | &pix->height, S5P_JPEG_MIN_HEIGHT, | 1187 | &pix->height, S5P_JPEG_MIN_HEIGHT, |
1021 | S5P_JPEG_MAX_HEIGHT, 0); | 1188 | S5P_JPEG_MAX_HEIGHT, 0); |
1022 | else | 1189 | else |
1023 | jpeg_bound_align_image(&pix->width, S5P_JPEG_MIN_WIDTH, | 1190 | jpeg_bound_align_image(ctx, &pix->width, S5P_JPEG_MIN_WIDTH, |
1024 | S5P_JPEG_MAX_WIDTH, fmt->h_align, | 1191 | S5P_JPEG_MAX_WIDTH, fmt->h_align, |
1025 | &pix->height, S5P_JPEG_MIN_HEIGHT, | 1192 | &pix->height, S5P_JPEG_MIN_HEIGHT, |
1026 | S5P_JPEG_MAX_HEIGHT, fmt->v_align); | 1193 | S5P_JPEG_MAX_HEIGHT, fmt->v_align); |
@@ -1142,7 +1309,7 @@ static int exynos4_jpeg_get_output_buffer_size(struct s5p_jpeg_ctx *ctx, | |||
1142 | else | 1309 | else |
1143 | wh_align = 1; | 1310 | wh_align = 1; |
1144 | 1311 | ||
1145 | jpeg_bound_align_image(&w, S5P_JPEG_MIN_WIDTH, | 1312 | jpeg_bound_align_image(ctx, &w, S5P_JPEG_MIN_WIDTH, |
1146 | S5P_JPEG_MAX_WIDTH, wh_align, | 1313 | S5P_JPEG_MAX_WIDTH, wh_align, |
1147 | &h, S5P_JPEG_MIN_HEIGHT, | 1314 | &h, S5P_JPEG_MIN_HEIGHT, |
1148 | S5P_JPEG_MAX_HEIGHT, wh_align); | 1315 | S5P_JPEG_MAX_HEIGHT, wh_align); |
@@ -1150,12 +1317,16 @@ static int exynos4_jpeg_get_output_buffer_size(struct s5p_jpeg_ctx *ctx, | |||
1150 | return w * h * fmt_depth >> 3; | 1317 | return w * h * fmt_depth >> 3; |
1151 | } | 1318 | } |
1152 | 1319 | ||
1320 | static int exynos3250_jpeg_try_downscale(struct s5p_jpeg_ctx *ctx, | ||
1321 | struct v4l2_rect *r); | ||
1322 | |||
1153 | static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f) | 1323 | static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f) |
1154 | { | 1324 | { |
1155 | struct vb2_queue *vq; | 1325 | struct vb2_queue *vq; |
1156 | struct s5p_jpeg_q_data *q_data = NULL; | 1326 | struct s5p_jpeg_q_data *q_data = NULL; |
1157 | struct v4l2_pix_format *pix = &f->fmt.pix; | 1327 | struct v4l2_pix_format *pix = &f->fmt.pix; |
1158 | struct v4l2_ctrl *ctrl_subs; | 1328 | struct v4l2_ctrl *ctrl_subs; |
1329 | struct v4l2_rect scale_rect; | ||
1159 | unsigned int f_type; | 1330 | unsigned int f_type; |
1160 | 1331 | ||
1161 | vq = v4l2_m2m_get_vq(ct->fh.m2m_ctx, f->type); | 1332 | vq = v4l2_m2m_get_vq(ct->fh.m2m_ctx, f->type); |
@@ -1200,6 +1371,35 @@ static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f) | |||
1200 | V4L2_CID_JPEG_CHROMA_SUBSAMPLING); | 1371 | V4L2_CID_JPEG_CHROMA_SUBSAMPLING); |
1201 | if (ctrl_subs) | 1372 | if (ctrl_subs) |
1202 | v4l2_ctrl_s_ctrl(ctrl_subs, q_data->fmt->subsampling); | 1373 | v4l2_ctrl_s_ctrl(ctrl_subs, q_data->fmt->subsampling); |
1374 | ct->crop_altered = false; | ||
1375 | } | ||
1376 | |||
1377 | /* | ||
1378 | * For decoding init crop_rect with capture buffer dimmensions which | ||
1379 | * contain aligned dimensions of the input JPEG image and do it only | ||
1380 | * if crop rectangle hasn't been altered by the user space e.g. with | ||
1381 | * S_SELECTION ioctl. For encoding assign output buffer dimensions. | ||
1382 | */ | ||
1383 | if (!ct->crop_altered && | ||
1384 | ((ct->mode == S5P_JPEG_DECODE && f_type == FMT_TYPE_CAPTURE) || | ||
1385 | (ct->mode == S5P_JPEG_ENCODE && f_type == FMT_TYPE_OUTPUT))) { | ||
1386 | ct->crop_rect.width = pix->width; | ||
1387 | ct->crop_rect.height = pix->height; | ||
1388 | } | ||
1389 | |||
1390 | /* | ||
1391 | * Prevent downscaling to YUV420 format by more than 2 | ||
1392 | * for Exynos3250 SoC as it produces broken raw image | ||
1393 | * in such cases. | ||
1394 | */ | ||
1395 | if (ct->mode == S5P_JPEG_DECODE && | ||
1396 | f_type == FMT_TYPE_CAPTURE && | ||
1397 | ct->jpeg->variant->version == SJPEG_EXYNOS3250 && | ||
1398 | pix->pixelformat == V4L2_PIX_FMT_YUV420 && | ||
1399 | ct->scale_factor > 2) { | ||
1400 | scale_rect.width = ct->out_q.w / 2; | ||
1401 | scale_rect.height = ct->out_q.h / 2; | ||
1402 | exynos3250_jpeg_try_downscale(ct, &scale_rect); | ||
1203 | } | 1403 | } |
1204 | 1404 | ||
1205 | return 0; | 1405 | return 0; |
@@ -1229,6 +1429,101 @@ static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv, | |||
1229 | return s5p_jpeg_s_fmt(fh_to_ctx(priv), f); | 1429 | return s5p_jpeg_s_fmt(fh_to_ctx(priv), f); |
1230 | } | 1430 | } |
1231 | 1431 | ||
1432 | static int exynos3250_jpeg_try_downscale(struct s5p_jpeg_ctx *ctx, | ||
1433 | struct v4l2_rect *r) | ||
1434 | { | ||
1435 | int w_ratio, h_ratio, scale_factor, cur_ratio, i; | ||
1436 | |||
1437 | w_ratio = ctx->out_q.w / r->width; | ||
1438 | h_ratio = ctx->out_q.h / r->height; | ||
1439 | |||
1440 | scale_factor = w_ratio > h_ratio ? w_ratio : h_ratio; | ||
1441 | scale_factor = clamp_val(scale_factor, 1, 8); | ||
1442 | |||
1443 | /* Align scale ratio to the nearest power of 2 */ | ||
1444 | for (i = 0; i <= 3; ++i) { | ||
1445 | cur_ratio = 1 << i; | ||
1446 | if (scale_factor <= cur_ratio) { | ||
1447 | ctx->scale_factor = cur_ratio; | ||
1448 | break; | ||
1449 | } | ||
1450 | } | ||
1451 | |||
1452 | r->width = round_down(ctx->out_q.w / ctx->scale_factor, 2); | ||
1453 | r->height = round_down(ctx->out_q.h / ctx->scale_factor, 2); | ||
1454 | |||
1455 | ctx->crop_rect.width = r->width; | ||
1456 | ctx->crop_rect.height = r->height; | ||
1457 | ctx->crop_rect.left = 0; | ||
1458 | ctx->crop_rect.top = 0; | ||
1459 | |||
1460 | ctx->crop_altered = true; | ||
1461 | |||
1462 | return 0; | ||
1463 | } | ||
1464 | |||
1465 | /* Return 1 if rectangle a is enclosed in rectangle b, or 0 otherwise. */ | ||
1466 | static int enclosed_rectangle(struct v4l2_rect *a, struct v4l2_rect *b) | ||
1467 | { | ||
1468 | if (a->left < b->left || a->top < b->top) | ||
1469 | return 0; | ||
1470 | if (a->left + a->width > b->left + b->width) | ||
1471 | return 0; | ||
1472 | if (a->top + a->height > b->top + b->height) | ||
1473 | return 0; | ||
1474 | |||
1475 | return 1; | ||
1476 | } | ||
1477 | |||
1478 | static int exynos3250_jpeg_try_crop(struct s5p_jpeg_ctx *ctx, | ||
1479 | struct v4l2_rect *r) | ||
1480 | { | ||
1481 | struct v4l2_rect base_rect; | ||
1482 | int w_step, h_step; | ||
1483 | |||
1484 | switch (ctx->cap_q.fmt->fourcc) { | ||
1485 | case V4L2_PIX_FMT_NV12: | ||
1486 | case V4L2_PIX_FMT_NV21: | ||
1487 | w_step = 1; | ||
1488 | h_step = 2; | ||
1489 | break; | ||
1490 | case V4L2_PIX_FMT_YUV420: | ||
1491 | w_step = 2; | ||
1492 | h_step = 2; | ||
1493 | break; | ||
1494 | default: | ||
1495 | w_step = 1; | ||
1496 | h_step = 1; | ||
1497 | break; | ||
1498 | } | ||
1499 | |||
1500 | base_rect.top = 0; | ||
1501 | base_rect.left = 0; | ||
1502 | base_rect.width = ctx->out_q.w; | ||
1503 | base_rect.height = ctx->out_q.h; | ||
1504 | |||
1505 | r->width = round_down(r->width, w_step); | ||
1506 | r->height = round_down(r->height, h_step); | ||
1507 | r->left = round_down(r->left, 2); | ||
1508 | r->top = round_down(r->top, 2); | ||
1509 | |||
1510 | if (!enclosed_rectangle(r, &base_rect)) | ||
1511 | return -EINVAL; | ||
1512 | |||
1513 | ctx->crop_rect.left = r->left; | ||
1514 | ctx->crop_rect.top = r->top; | ||
1515 | ctx->crop_rect.width = r->width; | ||
1516 | ctx->crop_rect.height = r->height; | ||
1517 | |||
1518 | ctx->crop_altered = true; | ||
1519 | |||
1520 | return 0; | ||
1521 | } | ||
1522 | |||
1523 | /* | ||
1524 | * V4L2 controls | ||
1525 | */ | ||
1526 | |||
1232 | static int s5p_jpeg_g_selection(struct file *file, void *priv, | 1527 | static int s5p_jpeg_g_selection(struct file *file, void *priv, |
1233 | struct v4l2_selection *s) | 1528 | struct v4l2_selection *s) |
1234 | { | 1529 | { |
@@ -1243,27 +1538,53 @@ static int s5p_jpeg_g_selection(struct file *file, void *priv, | |||
1243 | case V4L2_SEL_TGT_CROP: | 1538 | case V4L2_SEL_TGT_CROP: |
1244 | case V4L2_SEL_TGT_CROP_BOUNDS: | 1539 | case V4L2_SEL_TGT_CROP_BOUNDS: |
1245 | case V4L2_SEL_TGT_CROP_DEFAULT: | 1540 | case V4L2_SEL_TGT_CROP_DEFAULT: |
1246 | case V4L2_SEL_TGT_COMPOSE: | ||
1247 | case V4L2_SEL_TGT_COMPOSE_DEFAULT: | 1541 | case V4L2_SEL_TGT_COMPOSE_DEFAULT: |
1248 | s->r.width = ctx->out_q.w; | 1542 | s->r.width = ctx->out_q.w; |
1249 | s->r.height = ctx->out_q.h; | 1543 | s->r.height = ctx->out_q.h; |
1544 | s->r.left = 0; | ||
1545 | s->r.top = 0; | ||
1250 | break; | 1546 | break; |
1547 | case V4L2_SEL_TGT_COMPOSE: | ||
1251 | case V4L2_SEL_TGT_COMPOSE_BOUNDS: | 1548 | case V4L2_SEL_TGT_COMPOSE_BOUNDS: |
1252 | case V4L2_SEL_TGT_COMPOSE_PADDED: | 1549 | case V4L2_SEL_TGT_COMPOSE_PADDED: |
1253 | s->r.width = ctx->cap_q.w; | 1550 | s->r.width = ctx->crop_rect.width; |
1254 | s->r.height = ctx->cap_q.h; | 1551 | s->r.height = ctx->crop_rect.height; |
1552 | s->r.left = ctx->crop_rect.left; | ||
1553 | s->r.top = ctx->crop_rect.top; | ||
1255 | break; | 1554 | break; |
1256 | default: | 1555 | default: |
1257 | return -EINVAL; | 1556 | return -EINVAL; |
1258 | } | 1557 | } |
1259 | s->r.left = 0; | ||
1260 | s->r.top = 0; | ||
1261 | return 0; | 1558 | return 0; |
1262 | } | 1559 | } |
1263 | 1560 | ||
1264 | /* | 1561 | /* |
1265 | * V4L2 controls | 1562 | * V4L2 controls |
1266 | */ | 1563 | */ |
1564 | static int s5p_jpeg_s_selection(struct file *file, void *fh, | ||
1565 | struct v4l2_selection *s) | ||
1566 | { | ||
1567 | struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data); | ||
1568 | struct v4l2_rect *rect = &s->r; | ||
1569 | int ret = -EINVAL; | ||
1570 | |||
1571 | if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1572 | return -EINVAL; | ||
1573 | |||
1574 | if (s->target == V4L2_SEL_TGT_COMPOSE) { | ||
1575 | if (ctx->mode != S5P_JPEG_DECODE) | ||
1576 | return -EINVAL; | ||
1577 | if (ctx->jpeg->variant->version == SJPEG_EXYNOS3250) | ||
1578 | ret = exynos3250_jpeg_try_downscale(ctx, rect); | ||
1579 | } else if (s->target == V4L2_SEL_TGT_CROP) { | ||
1580 | if (ctx->mode != S5P_JPEG_ENCODE) | ||
1581 | return -EINVAL; | ||
1582 | if (ctx->jpeg->variant->version == SJPEG_EXYNOS3250) | ||
1583 | ret = exynos3250_jpeg_try_crop(ctx, rect); | ||
1584 | } | ||
1585 | |||
1586 | return ret; | ||
1587 | } | ||
1267 | 1588 | ||
1268 | static int s5p_jpeg_g_volatile_ctrl(struct v4l2_ctrl *ctrl) | 1589 | static int s5p_jpeg_g_volatile_ctrl(struct v4l2_ctrl *ctrl) |
1269 | { | 1590 | { |
@@ -1282,36 +1603,53 @@ static int s5p_jpeg_g_volatile_ctrl(struct v4l2_ctrl *ctrl) | |||
1282 | return 0; | 1603 | return 0; |
1283 | } | 1604 | } |
1284 | 1605 | ||
1285 | static int s5p_jpeg_try_ctrl(struct v4l2_ctrl *ctrl) | 1606 | static int s5p_jpeg_adjust_subs_ctrl(struct s5p_jpeg_ctx *ctx, int *ctrl_val) |
1286 | { | 1607 | { |
1287 | struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl); | 1608 | switch (ctx->jpeg->variant->version) { |
1288 | unsigned long flags; | 1609 | case SJPEG_S5P: |
1289 | int ret = 0; | 1610 | return 0; |
1290 | 1611 | case SJPEG_EXYNOS3250: | |
1291 | spin_lock_irqsave(&ctx->jpeg->slock, flags); | 1612 | /* |
1292 | 1613 | * The exynos3250 device can produce JPEG image only | |
1293 | if (ctrl->id == V4L2_CID_JPEG_CHROMA_SUBSAMPLING) { | 1614 | * of 4:4:4 subsampling when given RGB32 source image. |
1294 | if (ctx->jpeg->variant->version == SJPEG_S5P) | 1615 | */ |
1295 | goto error_free; | 1616 | if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB32) |
1617 | *ctrl_val = 0; | ||
1618 | break; | ||
1619 | case SJPEG_EXYNOS4: | ||
1296 | /* | 1620 | /* |
1297 | * The exynos4x12 device requires input raw image fourcc | 1621 | * The exynos4x12 device requires input raw image fourcc |
1298 | * to be V4L2_PIX_FMT_GREY if gray jpeg format | 1622 | * to be V4L2_PIX_FMT_GREY if gray jpeg format |
1299 | * is to be set. | 1623 | * is to be set. |
1300 | */ | 1624 | */ |
1301 | if (ctx->out_q.fmt->fourcc != V4L2_PIX_FMT_GREY && | 1625 | if (ctx->out_q.fmt->fourcc != V4L2_PIX_FMT_GREY && |
1302 | ctrl->val == V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY) { | 1626 | *ctrl_val == V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY) |
1303 | ret = -EINVAL; | 1627 | return -EINVAL; |
1304 | goto error_free; | 1628 | break; |
1305 | } | ||
1306 | /* | ||
1307 | * The exynos4x12 device requires resulting jpeg subsampling | ||
1308 | * not to be lower than the input raw image subsampling. | ||
1309 | */ | ||
1310 | if (ctx->out_q.fmt->subsampling > ctrl->val) | ||
1311 | ctrl->val = ctx->out_q.fmt->subsampling; | ||
1312 | } | 1629 | } |
1313 | 1630 | ||
1314 | error_free: | 1631 | /* |
1632 | * The exynos4x12 and exynos3250 devices require resulting | ||
1633 | * jpeg subsampling not to be lower than the input raw image | ||
1634 | * subsampling. | ||
1635 | */ | ||
1636 | if (ctx->out_q.fmt->subsampling > *ctrl_val) | ||
1637 | *ctrl_val = ctx->out_q.fmt->subsampling; | ||
1638 | |||
1639 | return 0; | ||
1640 | } | ||
1641 | |||
1642 | static int s5p_jpeg_try_ctrl(struct v4l2_ctrl *ctrl) | ||
1643 | { | ||
1644 | struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl); | ||
1645 | unsigned long flags; | ||
1646 | int ret = 0; | ||
1647 | |||
1648 | spin_lock_irqsave(&ctx->jpeg->slock, flags); | ||
1649 | |||
1650 | if (ctrl->id == V4L2_CID_JPEG_CHROMA_SUBSAMPLING) | ||
1651 | ret = s5p_jpeg_adjust_subs_ctrl(ctx, &ctrl->val); | ||
1652 | |||
1315 | spin_unlock_irqrestore(&ctx->jpeg->slock, flags); | 1653 | spin_unlock_irqrestore(&ctx->jpeg->slock, flags); |
1316 | return ret; | 1654 | return ret; |
1317 | } | 1655 | } |
@@ -1414,6 +1752,7 @@ static const struct v4l2_ioctl_ops s5p_jpeg_ioctl_ops = { | |||
1414 | .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, | 1752 | .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, |
1415 | 1753 | ||
1416 | .vidioc_g_selection = s5p_jpeg_g_selection, | 1754 | .vidioc_g_selection = s5p_jpeg_g_selection, |
1755 | .vidioc_s_selection = s5p_jpeg_s_selection, | ||
1417 | }; | 1756 | }; |
1418 | 1757 | ||
1419 | /* | 1758 | /* |
@@ -1604,6 +1943,135 @@ static void exynos4_jpeg_device_run(void *priv) | |||
1604 | spin_unlock_irqrestore(&ctx->jpeg->slock, flags); | 1943 | spin_unlock_irqrestore(&ctx->jpeg->slock, flags); |
1605 | } | 1944 | } |
1606 | 1945 | ||
1946 | static void exynos3250_jpeg_set_img_addr(struct s5p_jpeg_ctx *ctx) | ||
1947 | { | ||
1948 | struct s5p_jpeg *jpeg = ctx->jpeg; | ||
1949 | struct s5p_jpeg_fmt *fmt; | ||
1950 | struct vb2_buffer *vb; | ||
1951 | struct s5p_jpeg_addr jpeg_addr; | ||
1952 | u32 pix_size; | ||
1953 | |||
1954 | pix_size = ctx->cap_q.w * ctx->cap_q.h; | ||
1955 | |||
1956 | if (ctx->mode == S5P_JPEG_ENCODE) { | ||
1957 | vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); | ||
1958 | fmt = ctx->out_q.fmt; | ||
1959 | } else { | ||
1960 | vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); | ||
1961 | fmt = ctx->cap_q.fmt; | ||
1962 | } | ||
1963 | |||
1964 | jpeg_addr.y = vb2_dma_contig_plane_dma_addr(vb, 0); | ||
1965 | |||
1966 | if (fmt->colplanes == 2) { | ||
1967 | jpeg_addr.cb = jpeg_addr.y + pix_size; | ||
1968 | } else if (fmt->colplanes == 3) { | ||
1969 | jpeg_addr.cb = jpeg_addr.y + pix_size; | ||
1970 | if (fmt->fourcc == V4L2_PIX_FMT_YUV420) | ||
1971 | jpeg_addr.cr = jpeg_addr.cb + pix_size / 4; | ||
1972 | else | ||
1973 | jpeg_addr.cr = jpeg_addr.cb + pix_size / 2; | ||
1974 | } | ||
1975 | |||
1976 | exynos3250_jpeg_imgadr(jpeg->regs, &jpeg_addr); | ||
1977 | } | ||
1978 | |||
1979 | static void exynos3250_jpeg_set_jpeg_addr(struct s5p_jpeg_ctx *ctx) | ||
1980 | { | ||
1981 | struct s5p_jpeg *jpeg = ctx->jpeg; | ||
1982 | struct vb2_buffer *vb; | ||
1983 | unsigned int jpeg_addr = 0; | ||
1984 | |||
1985 | if (ctx->mode == S5P_JPEG_ENCODE) | ||
1986 | vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); | ||
1987 | else | ||
1988 | vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); | ||
1989 | |||
1990 | jpeg_addr = vb2_dma_contig_plane_dma_addr(vb, 0); | ||
1991 | exynos3250_jpeg_jpgadr(jpeg->regs, jpeg_addr); | ||
1992 | } | ||
1993 | |||
1994 | static void exynos3250_jpeg_device_run(void *priv) | ||
1995 | { | ||
1996 | struct s5p_jpeg_ctx *ctx = priv; | ||
1997 | struct s5p_jpeg *jpeg = ctx->jpeg; | ||
1998 | unsigned long flags; | ||
1999 | |||
2000 | spin_lock_irqsave(&ctx->jpeg->slock, flags); | ||
2001 | |||
2002 | exynos3250_jpeg_reset(jpeg->regs); | ||
2003 | exynos3250_jpeg_set_dma_num(jpeg->regs); | ||
2004 | exynos3250_jpeg_poweron(jpeg->regs); | ||
2005 | exynos3250_jpeg_clk_set(jpeg->regs); | ||
2006 | exynos3250_jpeg_proc_mode(jpeg->regs, ctx->mode); | ||
2007 | |||
2008 | if (ctx->mode == S5P_JPEG_ENCODE) { | ||
2009 | exynos3250_jpeg_input_raw_fmt(jpeg->regs, | ||
2010 | ctx->out_q.fmt->fourcc); | ||
2011 | exynos3250_jpeg_dri(jpeg->regs, ctx->restart_interval); | ||
2012 | |||
2013 | /* | ||
2014 | * JPEG IP allows storing 4 quantization tables | ||
2015 | * We fill table 0 for luma and table 1 for chroma | ||
2016 | */ | ||
2017 | s5p_jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality); | ||
2018 | s5p_jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality); | ||
2019 | /* use table 0 for Y */ | ||
2020 | exynos3250_jpeg_qtbl(jpeg->regs, 1, 0); | ||
2021 | /* use table 1 for Cb and Cr*/ | ||
2022 | exynos3250_jpeg_qtbl(jpeg->regs, 2, 1); | ||
2023 | exynos3250_jpeg_qtbl(jpeg->regs, 3, 1); | ||
2024 | |||
2025 | /* Y, Cb, Cr use Huffman table 0 */ | ||
2026 | exynos3250_jpeg_htbl_ac(jpeg->regs, 1); | ||
2027 | exynos3250_jpeg_htbl_dc(jpeg->regs, 1); | ||
2028 | exynos3250_jpeg_htbl_ac(jpeg->regs, 2); | ||
2029 | exynos3250_jpeg_htbl_dc(jpeg->regs, 2); | ||
2030 | exynos3250_jpeg_htbl_ac(jpeg->regs, 3); | ||
2031 | exynos3250_jpeg_htbl_dc(jpeg->regs, 3); | ||
2032 | |||
2033 | exynos3250_jpeg_set_x(jpeg->regs, ctx->crop_rect.width); | ||
2034 | exynos3250_jpeg_set_y(jpeg->regs, ctx->crop_rect.height); | ||
2035 | exynos3250_jpeg_stride(jpeg->regs, ctx->out_q.fmt->fourcc, | ||
2036 | ctx->out_q.w); | ||
2037 | exynos3250_jpeg_offset(jpeg->regs, ctx->crop_rect.left, | ||
2038 | ctx->crop_rect.top); | ||
2039 | exynos3250_jpeg_set_img_addr(ctx); | ||
2040 | exynos3250_jpeg_set_jpeg_addr(ctx); | ||
2041 | exynos3250_jpeg_subsampling_mode(jpeg->regs, ctx->subsampling); | ||
2042 | |||
2043 | /* ultimately comes from sizeimage from userspace */ | ||
2044 | exynos3250_jpeg_enc_stream_bound(jpeg->regs, ctx->cap_q.size); | ||
2045 | |||
2046 | if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565 || | ||
2047 | ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565X || | ||
2048 | ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB32) | ||
2049 | exynos3250_jpeg_set_y16(jpeg->regs, true); | ||
2050 | } else { | ||
2051 | exynos3250_jpeg_set_img_addr(ctx); | ||
2052 | exynos3250_jpeg_set_jpeg_addr(ctx); | ||
2053 | exynos3250_jpeg_stride(jpeg->regs, ctx->cap_q.fmt->fourcc, | ||
2054 | ctx->cap_q.w); | ||
2055 | exynos3250_jpeg_offset(jpeg->regs, 0, 0); | ||
2056 | exynos3250_jpeg_dec_scaling_ratio(jpeg->regs, | ||
2057 | ctx->scale_factor); | ||
2058 | exynos3250_jpeg_dec_stream_size(jpeg->regs, ctx->out_q.size); | ||
2059 | exynos3250_jpeg_output_raw_fmt(jpeg->regs, | ||
2060 | ctx->cap_q.fmt->fourcc); | ||
2061 | } | ||
2062 | |||
2063 | exynos3250_jpeg_interrupts_enable(jpeg->regs); | ||
2064 | |||
2065 | /* JPEG RGB to YCbCr conversion matrix */ | ||
2066 | exynos3250_jpeg_coef(jpeg->regs, ctx->mode); | ||
2067 | |||
2068 | exynos3250_jpeg_set_timer(jpeg->regs, EXYNOS3250_IRQ_TIMEOUT); | ||
2069 | jpeg->irq_status = 0; | ||
2070 | exynos3250_jpeg_start(jpeg->regs); | ||
2071 | |||
2072 | spin_unlock_irqrestore(&ctx->jpeg->slock, flags); | ||
2073 | } | ||
2074 | |||
1607 | static int s5p_jpeg_job_ready(void *priv) | 2075 | static int s5p_jpeg_job_ready(void *priv) |
1608 | { | 2076 | { |
1609 | struct s5p_jpeg_ctx *ctx = priv; | 2077 | struct s5p_jpeg_ctx *ctx = priv; |
@@ -1621,8 +2089,14 @@ static struct v4l2_m2m_ops s5p_jpeg_m2m_ops = { | |||
1621 | .device_run = s5p_jpeg_device_run, | 2089 | .device_run = s5p_jpeg_device_run, |
1622 | .job_ready = s5p_jpeg_job_ready, | 2090 | .job_ready = s5p_jpeg_job_ready, |
1623 | .job_abort = s5p_jpeg_job_abort, | 2091 | .job_abort = s5p_jpeg_job_abort, |
1624 | } | 2092 | }; |
1625 | ; | 2093 | |
2094 | static struct v4l2_m2m_ops exynos3250_jpeg_m2m_ops = { | ||
2095 | .device_run = exynos3250_jpeg_device_run, | ||
2096 | .job_ready = s5p_jpeg_job_ready, | ||
2097 | .job_abort = s5p_jpeg_job_abort, | ||
2098 | }; | ||
2099 | |||
1626 | static struct v4l2_m2m_ops exynos4_jpeg_m2m_ops = { | 2100 | static struct v4l2_m2m_ops exynos4_jpeg_m2m_ops = { |
1627 | .device_run = exynos4_jpeg_device_run, | 2101 | .device_run = exynos4_jpeg_device_run, |
1628 | .job_ready = s5p_jpeg_job_ready, | 2102 | .job_ready = s5p_jpeg_job_ready, |
@@ -1895,6 +2369,70 @@ static irqreturn_t exynos4_jpeg_irq(int irq, void *priv) | |||
1895 | return IRQ_HANDLED; | 2369 | return IRQ_HANDLED; |
1896 | } | 2370 | } |
1897 | 2371 | ||
2372 | static irqreturn_t exynos3250_jpeg_irq(int irq, void *dev_id) | ||
2373 | { | ||
2374 | struct s5p_jpeg *jpeg = dev_id; | ||
2375 | struct s5p_jpeg_ctx *curr_ctx; | ||
2376 | struct vb2_buffer *src_buf, *dst_buf; | ||
2377 | unsigned long payload_size = 0; | ||
2378 | enum vb2_buffer_state state = VB2_BUF_STATE_DONE; | ||
2379 | bool interrupt_timeout = false; | ||
2380 | u32 irq_status; | ||
2381 | |||
2382 | spin_lock(&jpeg->slock); | ||
2383 | |||
2384 | irq_status = exynos3250_jpeg_get_timer_status(jpeg->regs); | ||
2385 | if (irq_status & EXYNOS3250_TIMER_INT_STAT) { | ||
2386 | exynos3250_jpeg_clear_timer_status(jpeg->regs); | ||
2387 | interrupt_timeout = true; | ||
2388 | dev_err(jpeg->dev, "Interrupt timeout occurred.\n"); | ||
2389 | } | ||
2390 | |||
2391 | irq_status = exynos3250_jpeg_get_int_status(jpeg->regs); | ||
2392 | exynos3250_jpeg_clear_int_status(jpeg->regs, irq_status); | ||
2393 | |||
2394 | jpeg->irq_status |= irq_status; | ||
2395 | |||
2396 | curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev); | ||
2397 | |||
2398 | if (!curr_ctx) | ||
2399 | goto exit_unlock; | ||
2400 | |||
2401 | if ((irq_status & EXYNOS3250_HEADER_STAT) && | ||
2402 | (curr_ctx->mode == S5P_JPEG_DECODE)) { | ||
2403 | exynos3250_jpeg_rstart(jpeg->regs); | ||
2404 | goto exit_unlock; | ||
2405 | } | ||
2406 | |||
2407 | if (jpeg->irq_status & (EXYNOS3250_JPEG_DONE | | ||
2408 | EXYNOS3250_WDMA_DONE | | ||
2409 | EXYNOS3250_RDMA_DONE | | ||
2410 | EXYNOS3250_RESULT_STAT)) | ||
2411 | payload_size = exynos3250_jpeg_compressed_size(jpeg->regs); | ||
2412 | else if (interrupt_timeout) | ||
2413 | state = VB2_BUF_STATE_ERROR; | ||
2414 | else | ||
2415 | goto exit_unlock; | ||
2416 | |||
2417 | src_buf = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx); | ||
2418 | dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx); | ||
2419 | |||
2420 | dst_buf->v4l2_buf.timecode = src_buf->v4l2_buf.timecode; | ||
2421 | dst_buf->v4l2_buf.timestamp = src_buf->v4l2_buf.timestamp; | ||
2422 | |||
2423 | v4l2_m2m_buf_done(src_buf, state); | ||
2424 | if (curr_ctx->mode == S5P_JPEG_ENCODE) | ||
2425 | vb2_set_plane_payload(dst_buf, 0, payload_size); | ||
2426 | v4l2_m2m_buf_done(dst_buf, state); | ||
2427 | v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx); | ||
2428 | |||
2429 | curr_ctx->subsampling = | ||
2430 | exynos3250_jpeg_get_subsampling_mode(jpeg->regs); | ||
2431 | exit_unlock: | ||
2432 | spin_unlock(&jpeg->slock); | ||
2433 | return IRQ_HANDLED; | ||
2434 | } | ||
2435 | |||
1898 | static void *jpeg_get_drv_data(struct device *dev); | 2436 | static void *jpeg_get_drv_data(struct device *dev); |
1899 | 2437 | ||
1900 | /* | 2438 | /* |
@@ -1950,6 +2488,10 @@ static int s5p_jpeg_probe(struct platform_device *pdev) | |||
1950 | } | 2488 | } |
1951 | dev_dbg(&pdev->dev, "clock source %p\n", jpeg->clk); | 2489 | dev_dbg(&pdev->dev, "clock source %p\n", jpeg->clk); |
1952 | 2490 | ||
2491 | jpeg->sclk = clk_get(&pdev->dev, "sclk"); | ||
2492 | if (IS_ERR(jpeg->sclk)) | ||
2493 | dev_info(&pdev->dev, "sclk clock not available\n"); | ||
2494 | |||
1953 | /* v4l2 device */ | 2495 | /* v4l2 device */ |
1954 | ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev); | 2496 | ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev); |
1955 | if (ret) { | 2497 | if (ret) { |
@@ -2057,6 +2599,8 @@ device_register_rollback: | |||
2057 | 2599 | ||
2058 | clk_get_rollback: | 2600 | clk_get_rollback: |
2059 | clk_put(jpeg->clk); | 2601 | clk_put(jpeg->clk); |
2602 | if (!IS_ERR(jpeg->sclk)) | ||
2603 | clk_put(jpeg->sclk); | ||
2060 | 2604 | ||
2061 | return ret; | 2605 | return ret; |
2062 | } | 2606 | } |
@@ -2075,10 +2619,15 @@ static int s5p_jpeg_remove(struct platform_device *pdev) | |||
2075 | v4l2_m2m_release(jpeg->m2m_dev); | 2619 | v4l2_m2m_release(jpeg->m2m_dev); |
2076 | v4l2_device_unregister(&jpeg->v4l2_dev); | 2620 | v4l2_device_unregister(&jpeg->v4l2_dev); |
2077 | 2621 | ||
2078 | if (!pm_runtime_status_suspended(&pdev->dev)) | 2622 | if (!pm_runtime_status_suspended(&pdev->dev)) { |
2079 | clk_disable_unprepare(jpeg->clk); | 2623 | clk_disable_unprepare(jpeg->clk); |
2624 | if (!IS_ERR(jpeg->sclk)) | ||
2625 | clk_disable_unprepare(jpeg->sclk); | ||
2626 | } | ||
2080 | 2627 | ||
2081 | clk_put(jpeg->clk); | 2628 | clk_put(jpeg->clk); |
2629 | if (!IS_ERR(jpeg->sclk)) | ||
2630 | clk_put(jpeg->sclk); | ||
2082 | 2631 | ||
2083 | return 0; | 2632 | return 0; |
2084 | } | 2633 | } |
@@ -2088,6 +2637,8 @@ static int s5p_jpeg_runtime_suspend(struct device *dev) | |||
2088 | struct s5p_jpeg *jpeg = dev_get_drvdata(dev); | 2637 | struct s5p_jpeg *jpeg = dev_get_drvdata(dev); |
2089 | 2638 | ||
2090 | clk_disable_unprepare(jpeg->clk); | 2639 | clk_disable_unprepare(jpeg->clk); |
2640 | if (!IS_ERR(jpeg->sclk)) | ||
2641 | clk_disable_unprepare(jpeg->sclk); | ||
2091 | 2642 | ||
2092 | return 0; | 2643 | return 0; |
2093 | } | 2644 | } |
@@ -2102,15 +2653,24 @@ static int s5p_jpeg_runtime_resume(struct device *dev) | |||
2102 | if (ret < 0) | 2653 | if (ret < 0) |
2103 | return ret; | 2654 | return ret; |
2104 | 2655 | ||
2656 | if (!IS_ERR(jpeg->sclk)) { | ||
2657 | ret = clk_prepare_enable(jpeg->sclk); | ||
2658 | if (ret < 0) | ||
2659 | return ret; | ||
2660 | } | ||
2661 | |||
2105 | spin_lock_irqsave(&jpeg->slock, flags); | 2662 | spin_lock_irqsave(&jpeg->slock, flags); |
2106 | 2663 | ||
2107 | /* | 2664 | /* |
2108 | * JPEG IP allows storing two Huffman tables for each component | 2665 | * JPEG IP allows storing two Huffman tables for each component. |
2109 | * We fill table 0 for each component and do this here only | 2666 | * We fill table 0 for each component and do this here only |
2110 | * for S5PC210 device as Exynos4x12 requires programming its | 2667 | * for S5PC210 and Exynos3250 SoCs. Exynos4x12 SoC requires |
2111 | * Huffman tables each time the encoding process is initialized. | 2668 | * programming its Huffman tables each time the encoding process |
2669 | * is initialized, and thus it is accomplished in the device_run | ||
2670 | * callback of m2m_ops. | ||
2112 | */ | 2671 | */ |
2113 | if (jpeg->variant->version == SJPEG_S5P) { | 2672 | if (jpeg->variant->version == SJPEG_S5P || |
2673 | jpeg->variant->version == SJPEG_EXYNOS3250) { | ||
2114 | s5p_jpeg_set_hdctbl(jpeg->regs); | 2674 | s5p_jpeg_set_hdctbl(jpeg->regs); |
2115 | s5p_jpeg_set_hdctblg(jpeg->regs); | 2675 | s5p_jpeg_set_hdctblg(jpeg->regs); |
2116 | s5p_jpeg_set_hactbl(jpeg->regs); | 2676 | s5p_jpeg_set_hactbl(jpeg->regs); |
@@ -2150,6 +2710,13 @@ static struct s5p_jpeg_variant s5p_jpeg_drvdata = { | |||
2150 | .fmt_ver_flag = SJPEG_FMT_FLAG_S5P, | 2710 | .fmt_ver_flag = SJPEG_FMT_FLAG_S5P, |
2151 | }; | 2711 | }; |
2152 | 2712 | ||
2713 | static struct s5p_jpeg_variant exynos3250_jpeg_drvdata = { | ||
2714 | .version = SJPEG_EXYNOS3250, | ||
2715 | .jpeg_irq = exynos3250_jpeg_irq, | ||
2716 | .m2m_ops = &exynos3250_jpeg_m2m_ops, | ||
2717 | .fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS3250, | ||
2718 | }; | ||
2719 | |||
2153 | static struct s5p_jpeg_variant exynos4_jpeg_drvdata = { | 2720 | static struct s5p_jpeg_variant exynos4_jpeg_drvdata = { |
2154 | .version = SJPEG_EXYNOS4, | 2721 | .version = SJPEG_EXYNOS4, |
2155 | .jpeg_irq = exynos4_jpeg_irq, | 2722 | .jpeg_irq = exynos4_jpeg_irq, |
@@ -2162,8 +2729,11 @@ static const struct of_device_id samsung_jpeg_match[] = { | |||
2162 | .compatible = "samsung,s5pv210-jpeg", | 2729 | .compatible = "samsung,s5pv210-jpeg", |
2163 | .data = &s5p_jpeg_drvdata, | 2730 | .data = &s5p_jpeg_drvdata, |
2164 | }, { | 2731 | }, { |
2732 | .compatible = "samsung,exynos3250-jpeg", | ||
2733 | .data = &exynos3250_jpeg_drvdata, | ||
2734 | }, { | ||
2165 | .compatible = "samsung,exynos4210-jpeg", | 2735 | .compatible = "samsung,exynos4210-jpeg", |
2166 | .data = &s5p_jpeg_drvdata, | 2736 | .data = &exynos4_jpeg_drvdata, |
2167 | }, { | 2737 | }, { |
2168 | .compatible = "samsung,exynos4212-jpeg", | 2738 | .compatible = "samsung,exynos4212-jpeg", |
2169 | .data = &exynos4_jpeg_drvdata, | 2739 | .data = &exynos4_jpeg_drvdata, |
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.h b/drivers/media/platform/s5p-jpeg/jpeg-core.h index 3e4786329727..764b32de326b 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.h +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.h | |||
@@ -35,6 +35,8 @@ | |||
35 | #define S5P_JPEG_COEF32 0x6e | 35 | #define S5P_JPEG_COEF32 0x6e |
36 | #define S5P_JPEG_COEF33 0x13 | 36 | #define S5P_JPEG_COEF33 0x13 |
37 | 37 | ||
38 | #define EXYNOS3250_IRQ_TIMEOUT 0x10000000 | ||
39 | |||
38 | /* a selection of JPEG markers */ | 40 | /* a selection of JPEG markers */ |
39 | #define TEM 0x01 | 41 | #define TEM 0x01 |
40 | #define SOF0 0xc0 | 42 | #define SOF0 0xc0 |
@@ -49,9 +51,10 @@ | |||
49 | #define SJPEG_FMT_FLAG_DEC_CAPTURE (1 << 2) | 51 | #define SJPEG_FMT_FLAG_DEC_CAPTURE (1 << 2) |
50 | #define SJPEG_FMT_FLAG_DEC_OUTPUT (1 << 3) | 52 | #define SJPEG_FMT_FLAG_DEC_OUTPUT (1 << 3) |
51 | #define SJPEG_FMT_FLAG_S5P (1 << 4) | 53 | #define SJPEG_FMT_FLAG_S5P (1 << 4) |
52 | #define SJPEG_FMT_FLAG_EXYNOS4 (1 << 5) | 54 | #define SJPEG_FMT_FLAG_EXYNOS3250 (1 << 5) |
53 | #define SJPEG_FMT_RGB (1 << 6) | 55 | #define SJPEG_FMT_FLAG_EXYNOS4 (1 << 6) |
54 | #define SJPEG_FMT_NON_RGB (1 << 7) | 56 | #define SJPEG_FMT_RGB (1 << 7) |
57 | #define SJPEG_FMT_NON_RGB (1 << 8) | ||
55 | 58 | ||
56 | #define S5P_JPEG_ENCODE 0 | 59 | #define S5P_JPEG_ENCODE 0 |
57 | #define S5P_JPEG_DECODE 1 | 60 | #define S5P_JPEG_DECODE 1 |
@@ -65,8 +68,9 @@ | |||
65 | 68 | ||
66 | /* Version numbers */ | 69 | /* Version numbers */ |
67 | 70 | ||
68 | #define SJPEG_S5P 1 | 71 | #define SJPEG_S5P 1 |
69 | #define SJPEG_EXYNOS4 2 | 72 | #define SJPEG_EXYNOS3250 2 |
73 | #define SJPEG_EXYNOS4 3 | ||
70 | 74 | ||
71 | enum exynos4_jpeg_result { | 75 | enum exynos4_jpeg_result { |
72 | OK_ENC_OR_DEC, | 76 | OK_ENC_OR_DEC, |
@@ -95,8 +99,13 @@ enum exynos4_jpeg_img_quality_level { | |||
95 | * @regs: JPEG IP registers mapping | 99 | * @regs: JPEG IP registers mapping |
96 | * @irq: JPEG IP irq | 100 | * @irq: JPEG IP irq |
97 | * @clk: JPEG IP clock | 101 | * @clk: JPEG IP clock |
102 | * @sclk: Exynos3250 JPEG IP special clock | ||
98 | * @dev: JPEG IP struct device | 103 | * @dev: JPEG IP struct device |
99 | * @alloc_ctx: videobuf2 memory allocator's context | 104 | * @alloc_ctx: videobuf2 memory allocator's context |
105 | * @variant: driver variant to be used | ||
106 | * @irq_status interrupt flags set during single encode/decode | ||
107 | operation | ||
108 | |||
100 | */ | 109 | */ |
101 | struct s5p_jpeg { | 110 | struct s5p_jpeg { |
102 | struct mutex lock; | 111 | struct mutex lock; |
@@ -111,9 +120,11 @@ struct s5p_jpeg { | |||
111 | unsigned int irq; | 120 | unsigned int irq; |
112 | enum exynos4_jpeg_result irq_ret; | 121 | enum exynos4_jpeg_result irq_ret; |
113 | struct clk *clk; | 122 | struct clk *clk; |
123 | struct clk *sclk; | ||
114 | struct device *dev; | 124 | struct device *dev; |
115 | void *alloc_ctx; | 125 | void *alloc_ctx; |
116 | struct s5p_jpeg_variant *variant; | 126 | struct s5p_jpeg_variant *variant; |
127 | u32 irq_status; | ||
117 | }; | 128 | }; |
118 | 129 | ||
119 | struct s5p_jpeg_variant { | 130 | struct s5p_jpeg_variant { |
@@ -164,9 +175,15 @@ struct s5p_jpeg_q_data { | |||
164 | * @jpeg: JPEG IP device for this context | 175 | * @jpeg: JPEG IP device for this context |
165 | * @mode: compression (encode) operation or decompression (decode) | 176 | * @mode: compression (encode) operation or decompression (decode) |
166 | * @compr_quality: destination image quality in compression (encode) mode | 177 | * @compr_quality: destination image quality in compression (encode) mode |
178 | * @restart_interval: JPEG restart interval for JPEG encoding | ||
179 | * @subsampling: subsampling of a raw format or a JPEG | ||
167 | * @out_q: source (output) queue information | 180 | * @out_q: source (output) queue information |
168 | * @cap_fmt: destination (capture) queue queue information | 181 | * @cap_q: destination (capture) queue queue information |
182 | * @scale_factor: scale factor for JPEG decoding | ||
183 | * @crop_rect: a rectangle representing crop area of the output buffer | ||
184 | * @fh: V4L2 file handle | ||
169 | * @hdr_parsed: set if header has been parsed during decompression | 185 | * @hdr_parsed: set if header has been parsed during decompression |
186 | * @crop_altered: set if crop rectangle has been altered by the user space | ||
170 | * @ctrl_handler: controls handler | 187 | * @ctrl_handler: controls handler |
171 | */ | 188 | */ |
172 | struct s5p_jpeg_ctx { | 189 | struct s5p_jpeg_ctx { |
@@ -177,8 +194,11 @@ struct s5p_jpeg_ctx { | |||
177 | unsigned short subsampling; | 194 | unsigned short subsampling; |
178 | struct s5p_jpeg_q_data out_q; | 195 | struct s5p_jpeg_q_data out_q; |
179 | struct s5p_jpeg_q_data cap_q; | 196 | struct s5p_jpeg_q_data cap_q; |
197 | unsigned int scale_factor; | ||
198 | struct v4l2_rect crop_rect; | ||
180 | struct v4l2_fh fh; | 199 | struct v4l2_fh fh; |
181 | bool hdr_parsed; | 200 | bool hdr_parsed; |
201 | bool crop_altered; | ||
182 | struct v4l2_ctrl_handler ctrl_handler; | 202 | struct v4l2_ctrl_handler ctrl_handler; |
183 | }; | 203 | }; |
184 | 204 | ||
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.c b/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.c new file mode 100644 index 000000000000..d26e1f846553 --- /dev/null +++ b/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.c | |||
@@ -0,0 +1,487 @@ | |||
1 | /* linux/drivers/media/platform/exynos3250-jpeg/jpeg-hw.h | ||
2 | * | ||
3 | * Copyright (c) 2014 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * Author: Jacek Anaszewski <j.anaszewski@samsung.com> | ||
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 version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/io.h> | ||
14 | #include <linux/videodev2.h> | ||
15 | #include <linux/delay.h> | ||
16 | |||
17 | #include "jpeg-core.h" | ||
18 | #include "jpeg-regs.h" | ||
19 | #include "jpeg-hw-exynos3250.h" | ||
20 | |||
21 | void exynos3250_jpeg_reset(void __iomem *regs) | ||
22 | { | ||
23 | u32 reg = 0; | ||
24 | int count = 1000; | ||
25 | |||
26 | writel(1, regs + EXYNOS3250_SW_RESET); | ||
27 | /* no other way but polling for when JPEG IP becomes operational */ | ||
28 | while (reg != 0 && --count > 0) { | ||
29 | udelay(1); | ||
30 | cpu_relax(); | ||
31 | reg = readl(regs + EXYNOS3250_SW_RESET); | ||
32 | } | ||
33 | |||
34 | reg = 0; | ||
35 | count = 1000; | ||
36 | |||
37 | while (reg != 1 && --count > 0) { | ||
38 | writel(1, regs + EXYNOS3250_JPGDRI); | ||
39 | udelay(1); | ||
40 | cpu_relax(); | ||
41 | reg = readl(regs + EXYNOS3250_JPGDRI); | ||
42 | } | ||
43 | |||
44 | writel(0, regs + EXYNOS3250_JPGDRI); | ||
45 | } | ||
46 | |||
47 | void exynos3250_jpeg_poweron(void __iomem *regs) | ||
48 | { | ||
49 | writel(EXYNOS3250_POWER_ON, regs + EXYNOS3250_JPGCLKCON); | ||
50 | } | ||
51 | |||
52 | void exynos3250_jpeg_set_dma_num(void __iomem *regs) | ||
53 | { | ||
54 | writel(((EXYNOS3250_DMA_MO_COUNT << EXYNOS3250_WDMA_ISSUE_NUM_SHIFT) & | ||
55 | EXYNOS3250_WDMA_ISSUE_NUM_MASK) | | ||
56 | ((EXYNOS3250_DMA_MO_COUNT << EXYNOS3250_RDMA_ISSUE_NUM_SHIFT) & | ||
57 | EXYNOS3250_RDMA_ISSUE_NUM_MASK) | | ||
58 | ((EXYNOS3250_DMA_MO_COUNT << EXYNOS3250_ISSUE_GATHER_NUM_SHIFT) & | ||
59 | EXYNOS3250_ISSUE_GATHER_NUM_MASK), | ||
60 | regs + EXYNOS3250_DMA_ISSUE_NUM); | ||
61 | } | ||
62 | |||
63 | void exynos3250_jpeg_clk_set(void __iomem *base) | ||
64 | { | ||
65 | u32 reg; | ||
66 | |||
67 | reg = readl(base + EXYNOS3250_JPGCMOD) & ~EXYNOS3250_HALF_EN_MASK; | ||
68 | |||
69 | writel(reg | EXYNOS3250_HALF_EN, base + EXYNOS3250_JPGCMOD); | ||
70 | } | ||
71 | |||
72 | void exynos3250_jpeg_input_raw_fmt(void __iomem *regs, unsigned int fmt) | ||
73 | { | ||
74 | u32 reg; | ||
75 | |||
76 | reg = readl(regs + EXYNOS3250_JPGCMOD) & | ||
77 | EXYNOS3250_MODE_Y16_MASK; | ||
78 | |||
79 | switch (fmt) { | ||
80 | case V4L2_PIX_FMT_RGB32: | ||
81 | reg |= EXYNOS3250_MODE_SEL_ARGB8888; | ||
82 | break; | ||
83 | case V4L2_PIX_FMT_BGR32: | ||
84 | reg |= EXYNOS3250_MODE_SEL_ARGB8888 | EXYNOS3250_SRC_SWAP_RGB; | ||
85 | break; | ||
86 | case V4L2_PIX_FMT_RGB565: | ||
87 | reg |= EXYNOS3250_MODE_SEL_RGB565; | ||
88 | break; | ||
89 | case V4L2_PIX_FMT_RGB565X: | ||
90 | reg |= EXYNOS3250_MODE_SEL_RGB565 | EXYNOS3250_SRC_SWAP_RGB; | ||
91 | break; | ||
92 | case V4L2_PIX_FMT_YUYV: | ||
93 | reg |= EXYNOS3250_MODE_SEL_422_1P_LUM_CHR; | ||
94 | break; | ||
95 | case V4L2_PIX_FMT_YVYU: | ||
96 | reg |= EXYNOS3250_MODE_SEL_422_1P_LUM_CHR | | ||
97 | EXYNOS3250_SRC_SWAP_UV; | ||
98 | break; | ||
99 | case V4L2_PIX_FMT_UYVY: | ||
100 | reg |= EXYNOS3250_MODE_SEL_422_1P_CHR_LUM; | ||
101 | break; | ||
102 | case V4L2_PIX_FMT_VYUY: | ||
103 | reg |= EXYNOS3250_MODE_SEL_422_1P_CHR_LUM | | ||
104 | EXYNOS3250_SRC_SWAP_UV; | ||
105 | break; | ||
106 | case V4L2_PIX_FMT_NV12: | ||
107 | reg |= EXYNOS3250_MODE_SEL_420_2P | EXYNOS3250_SRC_NV12; | ||
108 | break; | ||
109 | case V4L2_PIX_FMT_NV21: | ||
110 | reg |= EXYNOS3250_MODE_SEL_420_2P | EXYNOS3250_SRC_NV21; | ||
111 | break; | ||
112 | case V4L2_PIX_FMT_YUV420: | ||
113 | reg |= EXYNOS3250_MODE_SEL_420_3P; | ||
114 | break; | ||
115 | default: | ||
116 | break; | ||
117 | |||
118 | } | ||
119 | |||
120 | writel(reg, regs + EXYNOS3250_JPGCMOD); | ||
121 | } | ||
122 | |||
123 | void exynos3250_jpeg_set_y16(void __iomem *regs, bool y16) | ||
124 | { | ||
125 | u32 reg; | ||
126 | |||
127 | reg = readl(regs + EXYNOS3250_JPGCMOD); | ||
128 | if (y16) | ||
129 | reg |= EXYNOS3250_MODE_Y16; | ||
130 | else | ||
131 | reg &= ~EXYNOS3250_MODE_Y16_MASK; | ||
132 | writel(reg, regs + EXYNOS3250_JPGCMOD); | ||
133 | } | ||
134 | |||
135 | void exynos3250_jpeg_proc_mode(void __iomem *regs, unsigned int mode) | ||
136 | { | ||
137 | u32 reg, m; | ||
138 | |||
139 | if (mode == S5P_JPEG_ENCODE) | ||
140 | m = EXYNOS3250_PROC_MODE_COMPR; | ||
141 | else | ||
142 | m = EXYNOS3250_PROC_MODE_DECOMPR; | ||
143 | reg = readl(regs + EXYNOS3250_JPGMOD); | ||
144 | reg &= ~EXYNOS3250_PROC_MODE_MASK; | ||
145 | reg |= m; | ||
146 | writel(reg, regs + EXYNOS3250_JPGMOD); | ||
147 | } | ||
148 | |||
149 | void exynos3250_jpeg_subsampling_mode(void __iomem *regs, unsigned int mode) | ||
150 | { | ||
151 | u32 reg, m = 0; | ||
152 | |||
153 | switch (mode) { | ||
154 | case V4L2_JPEG_CHROMA_SUBSAMPLING_444: | ||
155 | m = EXYNOS3250_SUBSAMPLING_MODE_444; | ||
156 | break; | ||
157 | case V4L2_JPEG_CHROMA_SUBSAMPLING_422: | ||
158 | m = EXYNOS3250_SUBSAMPLING_MODE_422; | ||
159 | break; | ||
160 | case V4L2_JPEG_CHROMA_SUBSAMPLING_420: | ||
161 | m = EXYNOS3250_SUBSAMPLING_MODE_420; | ||
162 | break; | ||
163 | } | ||
164 | |||
165 | reg = readl(regs + EXYNOS3250_JPGMOD); | ||
166 | reg &= ~EXYNOS3250_SUBSAMPLING_MODE_MASK; | ||
167 | reg |= m; | ||
168 | writel(reg, regs + EXYNOS3250_JPGMOD); | ||
169 | } | ||
170 | |||
171 | unsigned int exynos3250_jpeg_get_subsampling_mode(void __iomem *regs) | ||
172 | { | ||
173 | return readl(regs + EXYNOS3250_JPGMOD) & | ||
174 | EXYNOS3250_SUBSAMPLING_MODE_MASK; | ||
175 | } | ||
176 | |||
177 | void exynos3250_jpeg_dri(void __iomem *regs, unsigned int dri) | ||
178 | { | ||
179 | u32 reg; | ||
180 | |||
181 | reg = dri & EXYNOS3250_JPGDRI_MASK; | ||
182 | writel(reg, regs + EXYNOS3250_JPGDRI); | ||
183 | } | ||
184 | |||
185 | void exynos3250_jpeg_qtbl(void __iomem *regs, unsigned int t, unsigned int n) | ||
186 | { | ||
187 | unsigned long reg; | ||
188 | |||
189 | reg = readl(regs + EXYNOS3250_QHTBL); | ||
190 | reg &= ~EXYNOS3250_QT_NUM_MASK(t); | ||
191 | reg |= (n << EXYNOS3250_QT_NUM_SHIFT(t)) & | ||
192 | EXYNOS3250_QT_NUM_MASK(t); | ||
193 | writel(reg, regs + EXYNOS3250_QHTBL); | ||
194 | } | ||
195 | |||
196 | void exynos3250_jpeg_htbl_ac(void __iomem *regs, unsigned int t) | ||
197 | { | ||
198 | unsigned long reg; | ||
199 | |||
200 | reg = readl(regs + EXYNOS3250_QHTBL); | ||
201 | reg &= ~EXYNOS3250_HT_NUM_AC_MASK(t); | ||
202 | /* this driver uses table 0 for all color components */ | ||
203 | reg |= (0 << EXYNOS3250_HT_NUM_AC_SHIFT(t)) & | ||
204 | EXYNOS3250_HT_NUM_AC_MASK(t); | ||
205 | writel(reg, regs + EXYNOS3250_QHTBL); | ||
206 | } | ||
207 | |||
208 | void exynos3250_jpeg_htbl_dc(void __iomem *regs, unsigned int t) | ||
209 | { | ||
210 | unsigned long reg; | ||
211 | |||
212 | reg = readl(regs + EXYNOS3250_QHTBL); | ||
213 | reg &= ~EXYNOS3250_HT_NUM_DC_MASK(t); | ||
214 | /* this driver uses table 0 for all color components */ | ||
215 | reg |= (0 << EXYNOS3250_HT_NUM_DC_SHIFT(t)) & | ||
216 | EXYNOS3250_HT_NUM_DC_MASK(t); | ||
217 | writel(reg, regs + EXYNOS3250_QHTBL); | ||
218 | } | ||
219 | |||
220 | void exynos3250_jpeg_set_y(void __iomem *regs, unsigned int y) | ||
221 | { | ||
222 | u32 reg; | ||
223 | |||
224 | reg = y & EXYNOS3250_JPGY_MASK; | ||
225 | writel(reg, regs + EXYNOS3250_JPGY); | ||
226 | } | ||
227 | |||
228 | void exynos3250_jpeg_set_x(void __iomem *regs, unsigned int x) | ||
229 | { | ||
230 | u32 reg; | ||
231 | |||
232 | reg = x & EXYNOS3250_JPGX_MASK; | ||
233 | writel(reg, regs + EXYNOS3250_JPGX); | ||
234 | } | ||
235 | |||
236 | unsigned int exynos3250_jpeg_get_y(void __iomem *regs) | ||
237 | { | ||
238 | return readl(regs + EXYNOS3250_JPGY); | ||
239 | } | ||
240 | |||
241 | unsigned int exynos3250_jpeg_get_x(void __iomem *regs) | ||
242 | { | ||
243 | return readl(regs + EXYNOS3250_JPGX); | ||
244 | } | ||
245 | |||
246 | void exynos3250_jpeg_interrupts_enable(void __iomem *regs) | ||
247 | { | ||
248 | u32 reg; | ||
249 | |||
250 | reg = readl(regs + EXYNOS3250_JPGINTSE); | ||
251 | reg |= (EXYNOS3250_JPEG_DONE_EN | | ||
252 | EXYNOS3250_WDMA_DONE_EN | | ||
253 | EXYNOS3250_RDMA_DONE_EN | | ||
254 | EXYNOS3250_ENC_STREAM_INT_EN | | ||
255 | EXYNOS3250_CORE_DONE_EN | | ||
256 | EXYNOS3250_ERR_INT_EN | | ||
257 | EXYNOS3250_HEAD_INT_EN); | ||
258 | writel(reg, regs + EXYNOS3250_JPGINTSE); | ||
259 | } | ||
260 | |||
261 | void exynos3250_jpeg_enc_stream_bound(void __iomem *regs, unsigned int size) | ||
262 | { | ||
263 | u32 reg; | ||
264 | |||
265 | reg = size & EXYNOS3250_ENC_STREAM_BOUND_MASK; | ||
266 | writel(reg, regs + EXYNOS3250_ENC_STREAM_BOUND); | ||
267 | } | ||
268 | |||
269 | void exynos3250_jpeg_output_raw_fmt(void __iomem *regs, unsigned int fmt) | ||
270 | { | ||
271 | u32 reg; | ||
272 | |||
273 | switch (fmt) { | ||
274 | case V4L2_PIX_FMT_RGB32: | ||
275 | reg = EXYNOS3250_OUT_FMT_ARGB8888; | ||
276 | break; | ||
277 | case V4L2_PIX_FMT_BGR32: | ||
278 | reg = EXYNOS3250_OUT_FMT_ARGB8888 | EXYNOS3250_OUT_SWAP_RGB; | ||
279 | break; | ||
280 | case V4L2_PIX_FMT_RGB565: | ||
281 | reg = EXYNOS3250_OUT_FMT_RGB565; | ||
282 | break; | ||
283 | case V4L2_PIX_FMT_RGB565X: | ||
284 | reg = EXYNOS3250_OUT_FMT_RGB565 | EXYNOS3250_OUT_SWAP_RGB; | ||
285 | break; | ||
286 | case V4L2_PIX_FMT_YUYV: | ||
287 | reg = EXYNOS3250_OUT_FMT_422_1P_LUM_CHR; | ||
288 | break; | ||
289 | case V4L2_PIX_FMT_YVYU: | ||
290 | reg = EXYNOS3250_OUT_FMT_422_1P_LUM_CHR | | ||
291 | EXYNOS3250_OUT_SWAP_UV; | ||
292 | break; | ||
293 | case V4L2_PIX_FMT_UYVY: | ||
294 | reg = EXYNOS3250_OUT_FMT_422_1P_CHR_LUM; | ||
295 | break; | ||
296 | case V4L2_PIX_FMT_VYUY: | ||
297 | reg = EXYNOS3250_OUT_FMT_422_1P_CHR_LUM | | ||
298 | EXYNOS3250_OUT_SWAP_UV; | ||
299 | break; | ||
300 | case V4L2_PIX_FMT_NV12: | ||
301 | reg = EXYNOS3250_OUT_FMT_420_2P | EXYNOS3250_OUT_NV12; | ||
302 | break; | ||
303 | case V4L2_PIX_FMT_NV21: | ||
304 | reg = EXYNOS3250_OUT_FMT_420_2P | EXYNOS3250_OUT_NV21; | ||
305 | break; | ||
306 | case V4L2_PIX_FMT_YUV420: | ||
307 | reg = EXYNOS3250_OUT_FMT_420_3P; | ||
308 | break; | ||
309 | default: | ||
310 | reg = 0; | ||
311 | break; | ||
312 | } | ||
313 | |||
314 | writel(reg, regs + EXYNOS3250_OUTFORM); | ||
315 | } | ||
316 | |||
317 | void exynos3250_jpeg_jpgadr(void __iomem *regs, unsigned int addr) | ||
318 | { | ||
319 | writel(addr, regs + EXYNOS3250_JPG_JPGADR); | ||
320 | } | ||
321 | |||
322 | void exynos3250_jpeg_imgadr(void __iomem *regs, struct s5p_jpeg_addr *img_addr) | ||
323 | { | ||
324 | writel(img_addr->y, regs + EXYNOS3250_LUMA_BASE); | ||
325 | writel(img_addr->cb, regs + EXYNOS3250_CHROMA_BASE); | ||
326 | writel(img_addr->cr, regs + EXYNOS3250_CHROMA_CR_BASE); | ||
327 | } | ||
328 | |||
329 | void exynos3250_jpeg_stride(void __iomem *regs, unsigned int img_fmt, | ||
330 | unsigned int width) | ||
331 | { | ||
332 | u32 reg_luma = 0, reg_cr = 0, reg_cb = 0; | ||
333 | |||
334 | switch (img_fmt) { | ||
335 | case V4L2_PIX_FMT_RGB32: | ||
336 | reg_luma = 4 * width; | ||
337 | break; | ||
338 | case V4L2_PIX_FMT_RGB565: | ||
339 | case V4L2_PIX_FMT_RGB565X: | ||
340 | case V4L2_PIX_FMT_YUYV: | ||
341 | case V4L2_PIX_FMT_YVYU: | ||
342 | case V4L2_PIX_FMT_UYVY: | ||
343 | case V4L2_PIX_FMT_VYUY: | ||
344 | reg_luma = 2 * width; | ||
345 | break; | ||
346 | case V4L2_PIX_FMT_NV12: | ||
347 | case V4L2_PIX_FMT_NV21: | ||
348 | reg_luma = width; | ||
349 | reg_cb = reg_luma; | ||
350 | break; | ||
351 | case V4L2_PIX_FMT_YUV420: | ||
352 | reg_luma = width; | ||
353 | reg_cb = reg_cr = reg_luma / 2; | ||
354 | break; | ||
355 | default: | ||
356 | break; | ||
357 | } | ||
358 | |||
359 | writel(reg_luma, regs + EXYNOS3250_LUMA_STRIDE); | ||
360 | writel(reg_cb, regs + EXYNOS3250_CHROMA_STRIDE); | ||
361 | writel(reg_cr, regs + EXYNOS3250_CHROMA_CR_STRIDE); | ||
362 | } | ||
363 | |||
364 | void exynos3250_jpeg_offset(void __iomem *regs, unsigned int x_offset, | ||
365 | unsigned int y_offset) | ||
366 | { | ||
367 | u32 reg; | ||
368 | |||
369 | reg = (y_offset << EXYNOS3250_LUMA_YY_OFFSET_SHIFT) & | ||
370 | EXYNOS3250_LUMA_YY_OFFSET_MASK; | ||
371 | reg |= (x_offset << EXYNOS3250_LUMA_YX_OFFSET_SHIFT) & | ||
372 | EXYNOS3250_LUMA_YX_OFFSET_MASK; | ||
373 | |||
374 | writel(reg, regs + EXYNOS3250_LUMA_XY_OFFSET); | ||
375 | |||
376 | reg = (y_offset << EXYNOS3250_CHROMA_YY_OFFSET_SHIFT) & | ||
377 | EXYNOS3250_CHROMA_YY_OFFSET_MASK; | ||
378 | reg |= (x_offset << EXYNOS3250_CHROMA_YX_OFFSET_SHIFT) & | ||
379 | EXYNOS3250_CHROMA_YX_OFFSET_MASK; | ||
380 | |||
381 | writel(reg, regs + EXYNOS3250_CHROMA_XY_OFFSET); | ||
382 | |||
383 | reg = (y_offset << EXYNOS3250_CHROMA_CR_YY_OFFSET_SHIFT) & | ||
384 | EXYNOS3250_CHROMA_CR_YY_OFFSET_MASK; | ||
385 | reg |= (x_offset << EXYNOS3250_CHROMA_CR_YX_OFFSET_SHIFT) & | ||
386 | EXYNOS3250_CHROMA_CR_YX_OFFSET_MASK; | ||
387 | |||
388 | writel(reg, regs + EXYNOS3250_CHROMA_CR_XY_OFFSET); | ||
389 | } | ||
390 | |||
391 | void exynos3250_jpeg_coef(void __iomem *base, unsigned int mode) | ||
392 | { | ||
393 | if (mode == S5P_JPEG_ENCODE) { | ||
394 | writel(EXYNOS3250_JPEG_ENC_COEF1, | ||
395 | base + EXYNOS3250_JPG_COEF(1)); | ||
396 | writel(EXYNOS3250_JPEG_ENC_COEF2, | ||
397 | base + EXYNOS3250_JPG_COEF(2)); | ||
398 | writel(EXYNOS3250_JPEG_ENC_COEF3, | ||
399 | base + EXYNOS3250_JPG_COEF(3)); | ||
400 | } else { | ||
401 | writel(EXYNOS3250_JPEG_DEC_COEF1, | ||
402 | base + EXYNOS3250_JPG_COEF(1)); | ||
403 | writel(EXYNOS3250_JPEG_DEC_COEF2, | ||
404 | base + EXYNOS3250_JPG_COEF(2)); | ||
405 | writel(EXYNOS3250_JPEG_DEC_COEF3, | ||
406 | base + EXYNOS3250_JPG_COEF(3)); | ||
407 | } | ||
408 | } | ||
409 | |||
410 | void exynos3250_jpeg_start(void __iomem *regs) | ||
411 | { | ||
412 | writel(1, regs + EXYNOS3250_JSTART); | ||
413 | } | ||
414 | |||
415 | void exynos3250_jpeg_rstart(void __iomem *regs) | ||
416 | { | ||
417 | writel(1, regs + EXYNOS3250_JRSTART); | ||
418 | } | ||
419 | |||
420 | unsigned int exynos3250_jpeg_get_int_status(void __iomem *regs) | ||
421 | { | ||
422 | return readl(regs + EXYNOS3250_JPGINTST); | ||
423 | } | ||
424 | |||
425 | void exynos3250_jpeg_clear_int_status(void __iomem *regs, | ||
426 | unsigned int value) | ||
427 | { | ||
428 | return writel(value, regs + EXYNOS3250_JPGINTST); | ||
429 | } | ||
430 | |||
431 | unsigned int exynos3250_jpeg_operating(void __iomem *regs) | ||
432 | { | ||
433 | return readl(regs + S5P_JPGOPR) & EXYNOS3250_JPGOPR_MASK; | ||
434 | } | ||
435 | |||
436 | unsigned int exynos3250_jpeg_compressed_size(void __iomem *regs) | ||
437 | { | ||
438 | return readl(regs + EXYNOS3250_JPGCNT) & EXYNOS3250_JPGCNT_MASK; | ||
439 | } | ||
440 | |||
441 | void exynos3250_jpeg_dec_stream_size(void __iomem *regs, | ||
442 | unsigned int size) | ||
443 | { | ||
444 | writel(size & EXYNOS3250_DEC_STREAM_MASK, | ||
445 | regs + EXYNOS3250_DEC_STREAM_SIZE); | ||
446 | } | ||
447 | |||
448 | void exynos3250_jpeg_dec_scaling_ratio(void __iomem *regs, | ||
449 | unsigned int sratio) | ||
450 | { | ||
451 | switch (sratio) { | ||
452 | case 1: | ||
453 | default: | ||
454 | sratio = EXYNOS3250_DEC_SCALE_FACTOR_8_8; | ||
455 | break; | ||
456 | case 2: | ||
457 | sratio = EXYNOS3250_DEC_SCALE_FACTOR_4_8; | ||
458 | break; | ||
459 | case 4: | ||
460 | sratio = EXYNOS3250_DEC_SCALE_FACTOR_2_8; | ||
461 | break; | ||
462 | case 8: | ||
463 | sratio = EXYNOS3250_DEC_SCALE_FACTOR_1_8; | ||
464 | break; | ||
465 | } | ||
466 | |||
467 | writel(sratio & EXYNOS3250_DEC_SCALE_FACTOR_MASK, | ||
468 | regs + EXYNOS3250_DEC_SCALING_RATIO); | ||
469 | } | ||
470 | |||
471 | void exynos3250_jpeg_set_timer(void __iomem *regs, unsigned int time_value) | ||
472 | { | ||
473 | time_value &= EXYNOS3250_TIMER_INIT_MASK; | ||
474 | |||
475 | writel(EXYNOS3250_TIMER_INT_STAT | time_value, | ||
476 | regs + EXYNOS3250_TIMER_SE); | ||
477 | } | ||
478 | |||
479 | unsigned int exynos3250_jpeg_get_timer_status(void __iomem *regs) | ||
480 | { | ||
481 | return readl(regs + EXYNOS3250_TIMER_ST); | ||
482 | } | ||
483 | |||
484 | void exynos3250_jpeg_clear_timer_status(void __iomem *regs) | ||
485 | { | ||
486 | writel(EXYNOS3250_TIMER_INT_STAT, regs + EXYNOS3250_TIMER_ST); | ||
487 | } | ||
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.h b/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.h new file mode 100644 index 000000000000..b6e3be8b5008 --- /dev/null +++ b/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.h | |||
@@ -0,0 +1,60 @@ | |||
1 | /* linux/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.h | ||
2 | * | ||
3 | * Copyright (c) 2014 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * Author: Jacek Anaszewski <j.anaszewski@samsung.com> | ||
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 version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | #ifndef JPEG_HW_EXYNOS3250_H_ | ||
13 | #define JPEG_HW_EXYNOS3250_H_ | ||
14 | |||
15 | #include <linux/io.h> | ||
16 | #include <linux/videodev2.h> | ||
17 | |||
18 | #include "jpeg-regs.h" | ||
19 | |||
20 | void exynos3250_jpeg_reset(void __iomem *regs); | ||
21 | void exynos3250_jpeg_poweron(void __iomem *regs); | ||
22 | void exynos3250_jpeg_set_dma_num(void __iomem *regs); | ||
23 | void exynos3250_jpeg_clk_set(void __iomem *base); | ||
24 | void exynos3250_jpeg_input_raw_fmt(void __iomem *regs, unsigned int fmt); | ||
25 | void exynos3250_jpeg_output_raw_fmt(void __iomem *regs, unsigned int fmt); | ||
26 | void exynos3250_jpeg_set_y16(void __iomem *regs, bool y16); | ||
27 | void exynos3250_jpeg_proc_mode(void __iomem *regs, unsigned int mode); | ||
28 | void exynos3250_jpeg_subsampling_mode(void __iomem *regs, unsigned int mode); | ||
29 | unsigned int exynos3250_jpeg_get_subsampling_mode(void __iomem *regs); | ||
30 | void exynos3250_jpeg_dri(void __iomem *regs, unsigned int dri); | ||
31 | void exynos3250_jpeg_qtbl(void __iomem *regs, unsigned int t, unsigned int n); | ||
32 | void exynos3250_jpeg_htbl_ac(void __iomem *regs, unsigned int t); | ||
33 | void exynos3250_jpeg_htbl_dc(void __iomem *regs, unsigned int t); | ||
34 | void exynos3250_jpeg_set_y(void __iomem *regs, unsigned int y); | ||
35 | void exynos3250_jpeg_set_x(void __iomem *regs, unsigned int x); | ||
36 | void exynos3250_jpeg_interrupts_enable(void __iomem *regs); | ||
37 | void exynos3250_jpeg_enc_stream_bound(void __iomem *regs, unsigned int size); | ||
38 | void exynos3250_jpeg_outform_raw(void __iomem *regs, unsigned long format); | ||
39 | void exynos3250_jpeg_jpgadr(void __iomem *regs, unsigned int addr); | ||
40 | void exynos3250_jpeg_imgadr(void __iomem *regs, struct s5p_jpeg_addr *img_addr); | ||
41 | void exynos3250_jpeg_stride(void __iomem *regs, unsigned int img_fmt, | ||
42 | unsigned int width); | ||
43 | void exynos3250_jpeg_offset(void __iomem *regs, unsigned int x_offset, | ||
44 | unsigned int y_offset); | ||
45 | void exynos3250_jpeg_coef(void __iomem *base, unsigned int mode); | ||
46 | void exynos3250_jpeg_start(void __iomem *regs); | ||
47 | void exynos3250_jpeg_rstart(void __iomem *regs); | ||
48 | unsigned int exynos3250_jpeg_get_int_status(void __iomem *regs); | ||
49 | void exynos3250_jpeg_clear_int_status(void __iomem *regs, | ||
50 | unsigned int value); | ||
51 | unsigned int exynos3250_jpeg_operating(void __iomem *regs); | ||
52 | unsigned int exynos3250_jpeg_compressed_size(void __iomem *regs); | ||
53 | void exynos3250_jpeg_dec_stream_size(void __iomem *regs, unsigned int size); | ||
54 | void exynos3250_jpeg_dec_scaling_ratio(void __iomem *regs, unsigned int sratio); | ||
55 | void exynos3250_jpeg_set_timer(void __iomem *regs, unsigned int time_value); | ||
56 | unsigned int exynos3250_jpeg_get_timer_status(void __iomem *regs); | ||
57 | void exynos3250_jpeg_set_timer_status(void __iomem *regs); | ||
58 | void exynos3250_jpeg_clear_timer_status(void __iomem *regs); | ||
59 | |||
60 | #endif /* JPEG_HW_EXYNOS3250_H_ */ | ||
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-regs.h b/drivers/media/platform/s5p-jpeg/jpeg-regs.h index 57fb05bb8c77..050fc440248f 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-regs.h +++ b/drivers/media/platform/s5p-jpeg/jpeg-regs.h | |||
@@ -2,7 +2,7 @@ | |||
2 | * | 2 | * |
3 | * Register definition file for Samsung JPEG codec driver | 3 | * Register definition file for Samsung JPEG codec driver |
4 | * | 4 | * |
5 | * Copyright (c) 2011-2013 Samsung Electronics Co., Ltd. | 5 | * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd. |
6 | * http://www.samsung.com | 6 | * http://www.samsung.com |
7 | * | 7 | * |
8 | * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> | 8 | * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> |
@@ -373,5 +373,250 @@ | |||
373 | /* JPEG AC chrominance (values) Huffman table register */ | 373 | /* JPEG AC chrominance (values) Huffman table register */ |
374 | #define EXYNOS4_HUFF_TBL_HACCV 0x310 | 374 | #define EXYNOS4_HUFF_TBL_HACCV 0x310 |
375 | 375 | ||
376 | /* Register and bit definitions for Exynos 3250 */ | ||
377 | |||
378 | /* JPEG mode register */ | ||
379 | #define EXYNOS3250_JPGMOD 0x00 | ||
380 | #define EXYNOS3250_PROC_MODE_MASK (0x1 << 3) | ||
381 | #define EXYNOS3250_PROC_MODE_DECOMPR (0x1 << 3) | ||
382 | #define EXYNOS3250_PROC_MODE_COMPR (0x0 << 3) | ||
383 | #define EXYNOS3250_SUBSAMPLING_MODE_MASK (0x7 << 0) | ||
384 | #define EXYNOS3250_SUBSAMPLING_MODE_444 (0x0 << 0) | ||
385 | #define EXYNOS3250_SUBSAMPLING_MODE_422 (0x1 << 0) | ||
386 | #define EXYNOS3250_SUBSAMPLING_MODE_420 (0x2 << 0) | ||
387 | #define EXYNOS3250_SUBSAMPLING_MODE_411 (0x6 << 0) | ||
388 | #define EXYNOS3250_SUBSAMPLING_MODE_GRAY (0x3 << 0) | ||
389 | |||
390 | /* JPEG operation status register */ | ||
391 | #define EXYNOS3250_JPGOPR 0x04 | ||
392 | #define EXYNOS3250_JPGOPR_MASK 0x01 | ||
393 | |||
394 | /* Quantization and Huffman tables register */ | ||
395 | #define EXYNOS3250_QHTBL 0x08 | ||
396 | #define EXYNOS3250_QT_NUM_SHIFT(t) ((((t) - 1) << 1) + 8) | ||
397 | #define EXYNOS3250_QT_NUM_MASK(t) (0x3 << EXYNOS3250_QT_NUM_SHIFT(t)) | ||
398 | |||
399 | /* Huffman tables */ | ||
400 | #define EXYNOS3250_HT_NUM_AC_SHIFT(t) (((t) << 1) - 1) | ||
401 | #define EXYNOS3250_HT_NUM_AC_MASK(t) (0x1 << EXYNOS3250_HT_NUM_AC_SHIFT(t)) | ||
402 | |||
403 | #define EXYNOS3250_HT_NUM_DC_SHIFT(t) (((t) - 1) << 1) | ||
404 | #define EXYNOS3250_HT_NUM_DC_MASK(t) (0x1 << EXYNOS3250_HT_NUM_DC_SHIFT(t)) | ||
405 | |||
406 | /* JPEG restart interval register */ | ||
407 | #define EXYNOS3250_JPGDRI 0x0c | ||
408 | #define EXYNOS3250_JPGDRI_MASK 0xffff | ||
409 | |||
410 | /* JPEG vertical resolution register */ | ||
411 | #define EXYNOS3250_JPGY 0x10 | ||
412 | #define EXYNOS3250_JPGY_MASK 0xffff | ||
413 | |||
414 | /* JPEG horizontal resolution register */ | ||
415 | #define EXYNOS3250_JPGX 0x14 | ||
416 | #define EXYNOS3250_JPGX_MASK 0xffff | ||
417 | |||
418 | /* JPEG byte count register */ | ||
419 | #define EXYNOS3250_JPGCNT 0x18 | ||
420 | #define EXYNOS3250_JPGCNT_MASK 0xffffff | ||
421 | |||
422 | /* JPEG interrupt mask register */ | ||
423 | #define EXYNOS3250_JPGINTSE 0x1c | ||
424 | #define EXYNOS3250_JPEG_DONE_EN (1 << 11) | ||
425 | #define EXYNOS3250_WDMA_DONE_EN (1 << 10) | ||
426 | #define EXYNOS3250_RDMA_DONE_EN (1 << 9) | ||
427 | #define EXYNOS3250_ENC_STREAM_INT_EN (1 << 8) | ||
428 | #define EXYNOS3250_CORE_DONE_EN (1 << 5) | ||
429 | #define EXYNOS3250_ERR_INT_EN (1 << 4) | ||
430 | #define EXYNOS3250_HEAD_INT_EN (1 << 3) | ||
431 | |||
432 | /* JPEG interrupt status register */ | ||
433 | #define EXYNOS3250_JPGINTST 0x20 | ||
434 | #define EXYNOS3250_JPEG_DONE (1 << 11) | ||
435 | #define EXYNOS3250_WDMA_DONE (1 << 10) | ||
436 | #define EXYNOS3250_RDMA_DONE (1 << 9) | ||
437 | #define EXYNOS3250_ENC_STREAM_STAT (1 << 8) | ||
438 | #define EXYNOS3250_RESULT_STAT (1 << 5) | ||
439 | #define EXYNOS3250_STREAM_STAT (1 << 4) | ||
440 | #define EXYNOS3250_HEADER_STAT (1 << 3) | ||
441 | |||
442 | /* | ||
443 | * Base address of the luma component DMA buffer | ||
444 | * of the raw input or output image. | ||
445 | */ | ||
446 | #define EXYNOS3250_LUMA_BASE 0x100 | ||
447 | #define EXYNOS3250_SRC_TILE_EN_MASK 0x100 | ||
448 | |||
449 | /* Stride of source or destination luma raw image buffer */ | ||
450 | #define EXYNOS3250_LUMA_STRIDE 0x104 | ||
451 | |||
452 | /* Horizontal/vertical offset of active region in luma raw image buffer */ | ||
453 | #define EXYNOS3250_LUMA_XY_OFFSET 0x108 | ||
454 | #define EXYNOS3250_LUMA_YY_OFFSET_SHIFT 18 | ||
455 | #define EXYNOS3250_LUMA_YY_OFFSET_MASK (0x1fff << EXYNOS3250_LUMA_YY_OFFSET_SHIFT) | ||
456 | #define EXYNOS3250_LUMA_YX_OFFSET_SHIFT 2 | ||
457 | #define EXYNOS3250_LUMA_YX_OFFSET_MASK (0x1fff << EXYNOS3250_LUMA_YX_OFFSET_SHIFT) | ||
458 | |||
459 | /* | ||
460 | * Base address of the chroma(Cb) component DMA buffer | ||
461 | * of the raw input or output image. | ||
462 | */ | ||
463 | #define EXYNOS3250_CHROMA_BASE 0x10c | ||
464 | |||
465 | /* Stride of source or destination chroma(Cb) raw image buffer */ | ||
466 | #define EXYNOS3250_CHROMA_STRIDE 0x110 | ||
467 | |||
468 | /* Horizontal/vertical offset of active region in chroma(Cb) raw image buffer */ | ||
469 | #define EXYNOS3250_CHROMA_XY_OFFSET 0x114 | ||
470 | #define EXYNOS3250_CHROMA_YY_OFFSET_SHIFT 18 | ||
471 | #define EXYNOS3250_CHROMA_YY_OFFSET_MASK (0x1fff << EXYNOS3250_CHROMA_YY_OFFSET_SHIFT) | ||
472 | #define EXYNOS3250_CHROMA_YX_OFFSET_SHIFT 2 | ||
473 | #define EXYNOS3250_CHROMA_YX_OFFSET_MASK (0x1fff << EXYNOS3250_CHROMA_YX_OFFSET_SHIFT) | ||
474 | |||
475 | /* | ||
476 | * Base address of the chroma(Cr) component DMA buffer | ||
477 | * of the raw input or output image. | ||
478 | */ | ||
479 | #define EXYNOS3250_CHROMA_CR_BASE 0x118 | ||
480 | |||
481 | /* Stride of source or destination chroma(Cr) raw image buffer */ | ||
482 | #define EXYNOS3250_CHROMA_CR_STRIDE 0x11c | ||
483 | |||
484 | /* Horizontal/vertical offset of active region in chroma(Cb) raw image buffer */ | ||
485 | #define EXYNOS3250_CHROMA_CR_XY_OFFSET 0x120 | ||
486 | #define EXYNOS3250_CHROMA_CR_YY_OFFSET_SHIFT 18 | ||
487 | #define EXYNOS3250_CHROMA_CR_YY_OFFSET_MASK (0x1fff << EXYNOS3250_CHROMA_CR_YY_OFFSET_SHIFT) | ||
488 | #define EXYNOS3250_CHROMA_CR_YX_OFFSET_SHIFT 2 | ||
489 | #define EXYNOS3250_CHROMA_CR_YX_OFFSET_MASK (0x1fff << EXYNOS3250_CHROMA_CR_YX_OFFSET_SHIFT) | ||
490 | |||
491 | /* Raw image data r/w address register */ | ||
492 | #define EXYNOS3250_JPG_IMGADR 0x50 | ||
493 | |||
494 | /* Source or destination JPEG file DMA buffer address */ | ||
495 | #define EXYNOS3250_JPG_JPGADR 0x124 | ||
496 | |||
497 | /* Coefficients for RGB-to-YCbCr converter register */ | ||
498 | #define EXYNOS3250_JPG_COEF(n) (0x128 + (((n) - 1) << 2)) | ||
499 | #define EXYNOS3250_COEF_SHIFT(j) ((3 - (j)) << 3) | ||
500 | #define EXYNOS3250_COEF_MASK(j) (0xff << EXYNOS3250_COEF_SHIFT(j)) | ||
501 | |||
502 | /* Raw input format setting */ | ||
503 | #define EXYNOS3250_JPGCMOD 0x134 | ||
504 | #define EXYNOS3250_SRC_TILE_EN (0x1 << 10) | ||
505 | #define EXYNOS3250_SRC_NV_MASK (0x1 << 9) | ||
506 | #define EXYNOS3250_SRC_NV12 (0x0 << 9) | ||
507 | #define EXYNOS3250_SRC_NV21 (0x1 << 9) | ||
508 | #define EXYNOS3250_SRC_BIG_ENDIAN_MASK (0x1 << 8) | ||
509 | #define EXYNOS3250_SRC_BIG_ENDIAN (0x1 << 8) | ||
510 | #define EXYNOS3250_MODE_SEL_MASK (0x7 << 5) | ||
511 | #define EXYNOS3250_MODE_SEL_420_2P (0x0 << 5) | ||
512 | #define EXYNOS3250_MODE_SEL_422_1P_LUM_CHR (0x1 << 5) | ||
513 | #define EXYNOS3250_MODE_SEL_RGB565 (0x2 << 5) | ||
514 | #define EXYNOS3250_MODE_SEL_422_1P_CHR_LUM (0x3 << 5) | ||
515 | #define EXYNOS3250_MODE_SEL_ARGB8888 (0x4 << 5) | ||
516 | #define EXYNOS3250_MODE_SEL_420_3P (0x5 << 5) | ||
517 | #define EXYNOS3250_SRC_SWAP_RGB (0x1 << 3) | ||
518 | #define EXYNOS3250_SRC_SWAP_UV (0x1 << 2) | ||
519 | #define EXYNOS3250_MODE_Y16_MASK (0x1 << 1) | ||
520 | #define EXYNOS3250_MODE_Y16 (0x1 << 1) | ||
521 | #define EXYNOS3250_HALF_EN_MASK (0x1 << 0) | ||
522 | #define EXYNOS3250_HALF_EN (0x1 << 0) | ||
523 | |||
524 | /* Power on/off and clock down control */ | ||
525 | #define EXYNOS3250_JPGCLKCON 0x138 | ||
526 | #define EXYNOS3250_CLK_DOWN_READY (0x1 << 1) | ||
527 | #define EXYNOS3250_POWER_ON (0x1 << 0) | ||
528 | |||
529 | /* Start compression or decompression */ | ||
530 | #define EXYNOS3250_JSTART 0x13c | ||
531 | |||
532 | /* Restart decompression after header analysis */ | ||
533 | #define EXYNOS3250_JRSTART 0x140 | ||
534 | |||
535 | /* JPEG SW reset register */ | ||
536 | #define EXYNOS3250_SW_RESET 0x144 | ||
537 | |||
538 | /* JPEG timer setting register */ | ||
539 | #define EXYNOS3250_TIMER_SE 0x148 | ||
540 | #define EXYNOS3250_TIMER_INT_EN_SHIFT 31 | ||
541 | #define EXYNOS3250_TIMER_INT_EN (1 << EXYNOS3250_TIMER_INT_EN_SHIFT) | ||
542 | #define EXYNOS3250_TIMER_INIT_MASK 0x7fffffff | ||
543 | |||
544 | /* JPEG timer status register */ | ||
545 | #define EXYNOS3250_TIMER_ST 0x14c | ||
546 | #define EXYNOS3250_TIMER_INT_STAT_SHIFT 31 | ||
547 | #define EXYNOS3250_TIMER_INT_STAT (1 << EXYNOS3250_TIMER_INT_STAT_SHIFT) | ||
548 | #define EXYNOS3250_TIMER_CNT_SHIFT 0 | ||
549 | #define EXYNOS3250_TIMER_CNT_MASK 0x7fffffff | ||
550 | |||
551 | /* Command status register */ | ||
552 | #define EXYNOS3250_COMSTAT 0x150 | ||
553 | #define EXYNOS3250_CUR_PROC_MODE (0x1 << 1) | ||
554 | #define EXYNOS3250_CUR_COM_MODE (0x1 << 0) | ||
555 | |||
556 | /* JPEG decompression output format register */ | ||
557 | #define EXYNOS3250_OUTFORM 0x154 | ||
558 | #define EXYNOS3250_OUT_ALPHA_MASK (0xff << 24) | ||
559 | #define EXYNOS3250_OUT_TILE_EN (0x1 << 10) | ||
560 | #define EXYNOS3250_OUT_NV_MASK (0x1 << 9) | ||
561 | #define EXYNOS3250_OUT_NV12 (0x0 << 9) | ||
562 | #define EXYNOS3250_OUT_NV21 (0x1 << 9) | ||
563 | #define EXYNOS3250_OUT_BIG_ENDIAN_MASK (0x1 << 8) | ||
564 | #define EXYNOS3250_OUT_BIG_ENDIAN (0x1 << 8) | ||
565 | #define EXYNOS3250_OUT_SWAP_RGB (0x1 << 7) | ||
566 | #define EXYNOS3250_OUT_SWAP_UV (0x1 << 6) | ||
567 | #define EXYNOS3250_OUT_FMT_MASK (0x7 << 0) | ||
568 | #define EXYNOS3250_OUT_FMT_420_2P (0x0 << 0) | ||
569 | #define EXYNOS3250_OUT_FMT_422_1P_LUM_CHR (0x1 << 0) | ||
570 | #define EXYNOS3250_OUT_FMT_422_1P_CHR_LUM (0x3 << 0) | ||
571 | #define EXYNOS3250_OUT_FMT_420_3P (0x4 << 0) | ||
572 | #define EXYNOS3250_OUT_FMT_RGB565 (0x5 << 0) | ||
573 | #define EXYNOS3250_OUT_FMT_ARGB8888 (0x6 << 0) | ||
574 | |||
575 | /* Input JPEG stream byte size for decompression */ | ||
576 | #define EXYNOS3250_DEC_STREAM_SIZE 0x158 | ||
577 | #define EXYNOS3250_DEC_STREAM_MASK 0x1fffffff | ||
578 | |||
579 | /* The upper bound of the byte size of output compressed stream */ | ||
580 | #define EXYNOS3250_ENC_STREAM_BOUND 0x15c | ||
581 | #define EXYNOS3250_ENC_STREAM_BOUND_MASK 0xffffc0 | ||
582 | |||
583 | /* Scale-down ratio when decoding */ | ||
584 | #define EXYNOS3250_DEC_SCALING_RATIO 0x160 | ||
585 | #define EXYNOS3250_DEC_SCALE_FACTOR_MASK 0x3 | ||
586 | #define EXYNOS3250_DEC_SCALE_FACTOR_8_8 0x0 | ||
587 | #define EXYNOS3250_DEC_SCALE_FACTOR_4_8 0x1 | ||
588 | #define EXYNOS3250_DEC_SCALE_FACTOR_2_8 0x2 | ||
589 | #define EXYNOS3250_DEC_SCALE_FACTOR_1_8 0x3 | ||
590 | |||
591 | /* Error check */ | ||
592 | #define EXYNOS3250_CRC_RESULT 0x164 | ||
593 | |||
594 | /* RDMA and WDMA operation status register */ | ||
595 | #define EXYNOS3250_DMA_OPER_STATUS 0x168 | ||
596 | #define EXYNOS3250_WDMA_OPER_STATUS (0x1 << 1) | ||
597 | #define EXYNOS3250_RDMA_OPER_STATUS (0x1 << 0) | ||
598 | |||
599 | /* DMA issue gathering number and issue number settings */ | ||
600 | #define EXYNOS3250_DMA_ISSUE_NUM 0x16c | ||
601 | #define EXYNOS3250_WDMA_ISSUE_NUM_SHIFT 16 | ||
602 | #define EXYNOS3250_WDMA_ISSUE_NUM_MASK (0x7 << EXYNOS3250_WDMA_ISSUE_NUM_SHIFT) | ||
603 | #define EXYNOS3250_RDMA_ISSUE_NUM_SHIFT 8 | ||
604 | #define EXYNOS3250_RDMA_ISSUE_NUM_MASK (0x7 << EXYNOS3250_RDMA_ISSUE_NUM_SHIFT) | ||
605 | #define EXYNOS3250_ISSUE_GATHER_NUM_SHIFT 0 | ||
606 | #define EXYNOS3250_ISSUE_GATHER_NUM_MASK (0x7 << EXYNOS3250_ISSUE_GATHER_NUM_SHIFT) | ||
607 | #define EXYNOS3250_DMA_MO_COUNT 0x7 | ||
608 | |||
609 | /* Version register */ | ||
610 | #define EXYNOS3250_VERSION 0x1fc | ||
611 | |||
612 | /* RGB <-> YUV conversion coefficients */ | ||
613 | #define EXYNOS3250_JPEG_ENC_COEF1 0x01352e1e | ||
614 | #define EXYNOS3250_JPEG_ENC_COEF2 0x00b0ae83 | ||
615 | #define EXYNOS3250_JPEG_ENC_COEF3 0x020cdc13 | ||
616 | |||
617 | #define EXYNOS3250_JPEG_DEC_COEF1 0x04a80199 | ||
618 | #define EXYNOS3250_JPEG_DEC_COEF2 0x04a9a064 | ||
619 | #define EXYNOS3250_JPEG_DEC_COEF3 0x04a80102 | ||
620 | |||
376 | #endif /* JPEG_REGS_H_ */ | 621 | #endif /* JPEG_REGS_H_ */ |
377 | 622 | ||
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 41723180d10c..d35b0418ab37 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c | |||
@@ -162,7 +162,7 @@ static void s5p_mfc_watchdog_worker(struct work_struct *work) | |||
162 | /* Double check if there is at least one instance running. | 162 | /* Double check if there is at least one instance running. |
163 | * If no instance is in memory than no firmware should be present */ | 163 | * If no instance is in memory than no firmware should be present */ |
164 | if (dev->num_inst > 0) { | 164 | if (dev->num_inst > 0) { |
165 | ret = s5p_mfc_reload_firmware(dev); | 165 | ret = s5p_mfc_load_firmware(dev); |
166 | if (ret) { | 166 | if (ret) { |
167 | mfc_err("Failed to reload FW\n"); | 167 | mfc_err("Failed to reload FW\n"); |
168 | goto unlock; | 168 | goto unlock; |
@@ -724,7 +724,7 @@ static int s5p_mfc_open(struct file *file) | |||
724 | ret = -ENOMEM; | 724 | ret = -ENOMEM; |
725 | goto err_alloc; | 725 | goto err_alloc; |
726 | } | 726 | } |
727 | v4l2_fh_init(&ctx->fh, video_devdata(file)); | 727 | v4l2_fh_init(&ctx->fh, vdev); |
728 | file->private_data = &ctx->fh; | 728 | file->private_data = &ctx->fh; |
729 | v4l2_fh_add(&ctx->fh); | 729 | v4l2_fh_add(&ctx->fh); |
730 | ctx->dev = dev; | 730 | ctx->dev = dev; |
@@ -1351,7 +1351,7 @@ static struct s5p_mfc_variant mfc_drvdata_v5 = { | |||
1351 | .port_num = MFC_NUM_PORTS, | 1351 | .port_num = MFC_NUM_PORTS, |
1352 | .buf_size = &buf_size_v5, | 1352 | .buf_size = &buf_size_v5, |
1353 | .buf_align = &mfc_buf_align_v5, | 1353 | .buf_align = &mfc_buf_align_v5, |
1354 | .fw_name = "s5p-mfc.fw", | 1354 | .fw_name[0] = "s5p-mfc.fw", |
1355 | }; | 1355 | }; |
1356 | 1356 | ||
1357 | struct s5p_mfc_buf_size_v6 mfc_buf_size_v6 = { | 1357 | struct s5p_mfc_buf_size_v6 mfc_buf_size_v6 = { |
@@ -1378,7 +1378,12 @@ static struct s5p_mfc_variant mfc_drvdata_v6 = { | |||
1378 | .port_num = MFC_NUM_PORTS_V6, | 1378 | .port_num = MFC_NUM_PORTS_V6, |
1379 | .buf_size = &buf_size_v6, | 1379 | .buf_size = &buf_size_v6, |
1380 | .buf_align = &mfc_buf_align_v6, | 1380 | .buf_align = &mfc_buf_align_v6, |
1381 | .fw_name = "s5p-mfc-v6.fw", | 1381 | .fw_name[0] = "s5p-mfc-v6.fw", |
1382 | /* | ||
1383 | * v6-v2 firmware contains bug fixes and interface change | ||
1384 | * for init buffer command | ||
1385 | */ | ||
1386 | .fw_name[1] = "s5p-mfc-v6-v2.fw", | ||
1382 | }; | 1387 | }; |
1383 | 1388 | ||
1384 | struct s5p_mfc_buf_size_v6 mfc_buf_size_v7 = { | 1389 | struct s5p_mfc_buf_size_v6 mfc_buf_size_v7 = { |
@@ -1405,7 +1410,7 @@ static struct s5p_mfc_variant mfc_drvdata_v7 = { | |||
1405 | .port_num = MFC_NUM_PORTS_V7, | 1410 | .port_num = MFC_NUM_PORTS_V7, |
1406 | .buf_size = &buf_size_v7, | 1411 | .buf_size = &buf_size_v7, |
1407 | .buf_align = &mfc_buf_align_v7, | 1412 | .buf_align = &mfc_buf_align_v7, |
1408 | .fw_name = "s5p-mfc-v7.fw", | 1413 | .fw_name[0] = "s5p-mfc-v7.fw", |
1409 | }; | 1414 | }; |
1410 | 1415 | ||
1411 | struct s5p_mfc_buf_size_v6 mfc_buf_size_v8 = { | 1416 | struct s5p_mfc_buf_size_v6 mfc_buf_size_v8 = { |
@@ -1432,7 +1437,7 @@ static struct s5p_mfc_variant mfc_drvdata_v8 = { | |||
1432 | .port_num = MFC_NUM_PORTS_V8, | 1437 | .port_num = MFC_NUM_PORTS_V8, |
1433 | .buf_size = &buf_size_v8, | 1438 | .buf_size = &buf_size_v8, |
1434 | .buf_align = &mfc_buf_align_v8, | 1439 | .buf_align = &mfc_buf_align_v8, |
1435 | .fw_name = "s5p-mfc-v8.fw", | 1440 | .fw_name[0] = "s5p-mfc-v8.fw", |
1436 | }; | 1441 | }; |
1437 | 1442 | ||
1438 | static struct platform_device_id mfc_driver_ids[] = { | 1443 | static struct platform_device_id mfc_driver_ids[] = { |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index b04360cd34f0..01816ffb384b 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h | |||
@@ -38,6 +38,8 @@ | |||
38 | #define MFC_BANK2_ALIGN_ORDER 13 | 38 | #define MFC_BANK2_ALIGN_ORDER 13 |
39 | #define MFC_BASE_ALIGN_ORDER 17 | 39 | #define MFC_BASE_ALIGN_ORDER 17 |
40 | 40 | ||
41 | #define MFC_FW_MAX_VERSIONS 2 | ||
42 | |||
41 | #include <media/videobuf2-dma-contig.h> | 43 | #include <media/videobuf2-dma-contig.h> |
42 | 44 | ||
43 | static inline dma_addr_t s5p_mfc_mem_cookie(void *a, void *b) | 45 | static inline dma_addr_t s5p_mfc_mem_cookie(void *a, void *b) |
@@ -163,6 +165,11 @@ enum s5p_mfc_decode_arg { | |||
163 | MFC_DEC_RES_CHANGE, | 165 | MFC_DEC_RES_CHANGE, |
164 | }; | 166 | }; |
165 | 167 | ||
168 | enum s5p_mfc_fw_ver { | ||
169 | MFC_FW_V1, | ||
170 | MFC_FW_V2, | ||
171 | }; | ||
172 | |||
166 | #define MFC_BUF_FLAG_USED (1 << 0) | 173 | #define MFC_BUF_FLAG_USED (1 << 0) |
167 | #define MFC_BUF_FLAG_EOS (1 << 1) | 174 | #define MFC_BUF_FLAG_EOS (1 << 1) |
168 | 175 | ||
@@ -225,7 +232,7 @@ struct s5p_mfc_variant { | |||
225 | u32 version_bit; | 232 | u32 version_bit; |
226 | struct s5p_mfc_buf_size *buf_size; | 233 | struct s5p_mfc_buf_size *buf_size; |
227 | struct s5p_mfc_buf_align *buf_align; | 234 | struct s5p_mfc_buf_align *buf_align; |
228 | char *fw_name; | 235 | char *fw_name[MFC_FW_MAX_VERSIONS]; |
229 | }; | 236 | }; |
230 | 237 | ||
231 | /** | 238 | /** |
@@ -287,6 +294,7 @@ struct s5p_mfc_priv_buf { | |||
287 | * @warn_start: hardware error code from which warnings start | 294 | * @warn_start: hardware error code from which warnings start |
288 | * @mfc_ops: ops structure holding HW operation function pointers | 295 | * @mfc_ops: ops structure holding HW operation function pointers |
289 | * @mfc_cmds: cmd structure holding HW commands function pointers | 296 | * @mfc_cmds: cmd structure holding HW commands function pointers |
297 | * @fw_ver: loaded firmware sub-version | ||
290 | * | 298 | * |
291 | */ | 299 | */ |
292 | struct s5p_mfc_dev { | 300 | struct s5p_mfc_dev { |
@@ -331,6 +339,7 @@ struct s5p_mfc_dev { | |||
331 | struct s5p_mfc_hw_ops *mfc_ops; | 339 | struct s5p_mfc_hw_ops *mfc_ops; |
332 | struct s5p_mfc_hw_cmds *mfc_cmds; | 340 | struct s5p_mfc_hw_cmds *mfc_cmds; |
333 | const struct s5p_mfc_regs *mfc_regs; | 341 | const struct s5p_mfc_regs *mfc_regs; |
342 | enum s5p_mfc_fw_ver fw_ver; | ||
334 | }; | 343 | }; |
335 | 344 | ||
336 | /** | 345 | /** |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c index 6c3f8f743900..ca9f78922832 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | |||
@@ -38,8 +38,7 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) | |||
38 | dev->fw_virt_addr = dma_alloc_coherent(dev->mem_dev_l, dev->fw_size, | 38 | dev->fw_virt_addr = dma_alloc_coherent(dev->mem_dev_l, dev->fw_size, |
39 | &dev->bank1, GFP_KERNEL); | 39 | &dev->bank1, GFP_KERNEL); |
40 | 40 | ||
41 | if (IS_ERR_OR_NULL(dev->fw_virt_addr)) { | 41 | if (!dev->fw_virt_addr) { |
42 | dev->fw_virt_addr = NULL; | ||
43 | mfc_err("Allocating bitprocessor buffer failed\n"); | 42 | mfc_err("Allocating bitprocessor buffer failed\n"); |
44 | return -ENOMEM; | 43 | return -ENOMEM; |
45 | } | 44 | } |
@@ -48,7 +47,7 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) | |||
48 | bank2_virt = dma_alloc_coherent(dev->mem_dev_r, 1 << MFC_BASE_ALIGN_ORDER, | 47 | bank2_virt = dma_alloc_coherent(dev->mem_dev_r, 1 << MFC_BASE_ALIGN_ORDER, |
49 | &bank2_dma_addr, GFP_KERNEL); | 48 | &bank2_dma_addr, GFP_KERNEL); |
50 | 49 | ||
51 | if (IS_ERR(dev->fw_virt_addr)) { | 50 | if (!bank2_virt) { |
52 | mfc_err("Allocating bank2 base failed\n"); | 51 | mfc_err("Allocating bank2 base failed\n"); |
53 | dma_free_coherent(dev->mem_dev_l, dev->fw_size, | 52 | dma_free_coherent(dev->mem_dev_l, dev->fw_size, |
54 | dev->fw_virt_addr, dev->bank1); | 53 | dev->fw_virt_addr, dev->bank1); |
@@ -78,47 +77,23 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) | |||
78 | int s5p_mfc_load_firmware(struct s5p_mfc_dev *dev) | 77 | int s5p_mfc_load_firmware(struct s5p_mfc_dev *dev) |
79 | { | 78 | { |
80 | struct firmware *fw_blob; | 79 | struct firmware *fw_blob; |
81 | int err; | 80 | int i, err = -EINVAL; |
82 | 81 | ||
83 | /* Firmare has to be present as a separate file or compiled | 82 | /* Firmare has to be present as a separate file or compiled |
84 | * into kernel. */ | 83 | * into kernel. */ |
85 | mfc_debug_enter(); | 84 | mfc_debug_enter(); |
86 | 85 | ||
87 | err = request_firmware((const struct firmware **)&fw_blob, | 86 | for (i = MFC_FW_MAX_VERSIONS - 1; i >= 0; i--) { |
88 | dev->variant->fw_name, dev->v4l2_dev.dev); | 87 | if (!dev->variant->fw_name[i]) |
89 | if (err != 0) { | 88 | continue; |
90 | mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n"); | 89 | err = request_firmware((const struct firmware **)&fw_blob, |
91 | return -EINVAL; | 90 | dev->variant->fw_name[i], dev->v4l2_dev.dev); |
92 | } | 91 | if (!err) { |
93 | if (fw_blob->size > dev->fw_size) { | 92 | dev->fw_ver = (enum s5p_mfc_fw_ver) i; |
94 | mfc_err("MFC firmware is too big to be loaded\n"); | 93 | break; |
95 | release_firmware(fw_blob); | 94 | } |
96 | return -ENOMEM; | ||
97 | } | ||
98 | if (!dev->fw_virt_addr) { | ||
99 | mfc_err("MFC firmware is not allocated\n"); | ||
100 | release_firmware(fw_blob); | ||
101 | return -EINVAL; | ||
102 | } | 95 | } |
103 | memcpy(dev->fw_virt_addr, fw_blob->data, fw_blob->size); | ||
104 | wmb(); | ||
105 | release_firmware(fw_blob); | ||
106 | mfc_debug_leave(); | ||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | /* Reload firmware to MFC */ | ||
111 | int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev) | ||
112 | { | ||
113 | struct firmware *fw_blob; | ||
114 | int err; | ||
115 | |||
116 | /* Firmare has to be present as a separate file or compiled | ||
117 | * into kernel. */ | ||
118 | mfc_debug_enter(); | ||
119 | 96 | ||
120 | err = request_firmware((const struct firmware **)&fw_blob, | ||
121 | dev->variant->fw_name, dev->v4l2_dev.dev); | ||
122 | if (err != 0) { | 97 | if (err != 0) { |
123 | mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n"); | 98 | mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n"); |
124 | return -EINVAL; | 99 | return -EINVAL; |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c index 4d93835dec9d..9103258b7df3 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | |||
@@ -436,6 +436,7 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) | |||
436 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); | 436 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); |
437 | int ret = 0; | 437 | int ret = 0; |
438 | struct v4l2_pix_format_mplane *pix_mp; | 438 | struct v4l2_pix_format_mplane *pix_mp; |
439 | struct s5p_mfc_buf_size *buf_size = dev->variant->buf_size; | ||
439 | 440 | ||
440 | mfc_debug_enter(); | 441 | mfc_debug_enter(); |
441 | ret = vidioc_try_fmt(file, priv, f); | 442 | ret = vidioc_try_fmt(file, priv, f); |
@@ -459,11 +460,13 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) | |||
459 | mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode); | 460 | mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode); |
460 | pix_mp->height = 0; | 461 | pix_mp->height = 0; |
461 | pix_mp->width = 0; | 462 | pix_mp->width = 0; |
462 | if (pix_mp->plane_fmt[0].sizeimage) | 463 | if (pix_mp->plane_fmt[0].sizeimage == 0) |
463 | ctx->dec_src_buf_size = pix_mp->plane_fmt[0].sizeimage; | ||
464 | else | ||
465 | pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size = | 464 | pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size = |
466 | DEF_CPB_SIZE; | 465 | DEF_CPB_SIZE; |
466 | else if (pix_mp->plane_fmt[0].sizeimage > buf_size->cpb) | ||
467 | ctx->dec_src_buf_size = buf_size->cpb; | ||
468 | else | ||
469 | ctx->dec_src_buf_size = pix_mp->plane_fmt[0].sizeimage; | ||
467 | pix_mp->plane_fmt[0].bytesperline = 0; | 470 | pix_mp->plane_fmt[0].bytesperline = 0; |
468 | ctx->state = MFCINST_INIT; | 471 | ctx->state = MFCINST_INIT; |
469 | ret = 0; | 472 | ret = 0; |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c index 4f5e0ead90c6..c1c12f8d8f68 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c | |||
@@ -48,6 +48,8 @@ | |||
48 | #define WRITEL(data, reg) \ | 48 | #define WRITEL(data, reg) \ |
49 | (WARN_ON_ONCE(!(reg)) ? 0 : writel((data), (reg))) | 49 | (WARN_ON_ONCE(!(reg)) ? 0 : writel((data), (reg))) |
50 | 50 | ||
51 | #define IS_MFCV6_V2(dev) (!IS_MFCV7_PLUS(dev) && dev->fw_ver == MFC_FW_V2) | ||
52 | |||
51 | /* Allocate temporary buffers for decoding */ | 53 | /* Allocate temporary buffers for decoding */ |
52 | static int s5p_mfc_alloc_dec_temp_buffers_v6(struct s5p_mfc_ctx *ctx) | 54 | static int s5p_mfc_alloc_dec_temp_buffers_v6(struct s5p_mfc_ctx *ctx) |
53 | { | 55 | { |
@@ -1352,7 +1354,7 @@ static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx) | |||
1352 | WRITEL(ctx->display_delay, mfc_regs->d_display_delay); | 1354 | WRITEL(ctx->display_delay, mfc_regs->d_display_delay); |
1353 | } | 1355 | } |
1354 | 1356 | ||
1355 | if (IS_MFCV7_PLUS(dev)) { | 1357 | if (IS_MFCV7_PLUS(dev) || IS_MFCV6_V2(dev)) { |
1356 | WRITEL(reg, mfc_regs->d_dec_options); | 1358 | WRITEL(reg, mfc_regs->d_dec_options); |
1357 | reg = 0; | 1359 | reg = 0; |
1358 | } | 1360 | } |
@@ -1367,7 +1369,7 @@ static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx) | |||
1367 | if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) | 1369 | if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) |
1368 | reg |= (0x1 << S5P_FIMV_D_OPT_TILE_MODE_SHIFT_V6); | 1370 | reg |= (0x1 << S5P_FIMV_D_OPT_TILE_MODE_SHIFT_V6); |
1369 | 1371 | ||
1370 | if (IS_MFCV7_PLUS(dev)) | 1372 | if (IS_MFCV7_PLUS(dev) || IS_MFCV6_V2(dev)) |
1371 | WRITEL(reg, mfc_regs->d_init_buffer_options); | 1373 | WRITEL(reg, mfc_regs->d_init_buffer_options); |
1372 | else | 1374 | else |
1373 | WRITEL(reg, mfc_regs->d_dec_options); | 1375 | WRITEL(reg, mfc_regs->d_dec_options); |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c index 11d5f1dada32..b6a8be97a96c 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #include "s5p_mfc_pm.h" | 21 | #include "s5p_mfc_pm.h" |
22 | 22 | ||
23 | #define MFC_GATE_CLK_NAME "mfc" | 23 | #define MFC_GATE_CLK_NAME "mfc" |
24 | #define MFC_SCLK_NAME "sclk-mfc" | ||
25 | #define MFC_SCLK_RATE (200 * 1000000) | ||
24 | 26 | ||
25 | #define CLK_DEBUG | 27 | #define CLK_DEBUG |
26 | 28 | ||
@@ -50,6 +52,20 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev *dev) | |||
50 | goto err_p_ip_clk; | 52 | goto err_p_ip_clk; |
51 | } | 53 | } |
52 | 54 | ||
55 | if (dev->variant->version != MFC_VERSION_V6) { | ||
56 | pm->clock = clk_get(&dev->plat_dev->dev, MFC_SCLK_NAME); | ||
57 | if (IS_ERR(pm->clock)) { | ||
58 | mfc_info("Failed to get MFC special clock control\n"); | ||
59 | } else { | ||
60 | clk_set_rate(pm->clock, MFC_SCLK_RATE); | ||
61 | ret = clk_prepare_enable(pm->clock); | ||
62 | if (ret) { | ||
63 | mfc_err("Failed to enable MFC special clock\n"); | ||
64 | goto err_s_clk; | ||
65 | } | ||
66 | } | ||
67 | } | ||
68 | |||
53 | atomic_set(&pm->power, 0); | 69 | atomic_set(&pm->power, 0); |
54 | #ifdef CONFIG_PM_RUNTIME | 70 | #ifdef CONFIG_PM_RUNTIME |
55 | pm->device = &dev->plat_dev->dev; | 71 | pm->device = &dev->plat_dev->dev; |
@@ -59,6 +75,9 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev *dev) | |||
59 | atomic_set(&clk_ref, 0); | 75 | atomic_set(&clk_ref, 0); |
60 | #endif | 76 | #endif |
61 | return 0; | 77 | return 0; |
78 | |||
79 | err_s_clk: | ||
80 | clk_put(pm->clock); | ||
62 | err_p_ip_clk: | 81 | err_p_ip_clk: |
63 | clk_put(pm->clock_gate); | 82 | clk_put(pm->clock_gate); |
64 | err_g_ip_clk: | 83 | err_g_ip_clk: |
@@ -67,6 +86,11 @@ err_g_ip_clk: | |||
67 | 86 | ||
68 | void s5p_mfc_final_pm(struct s5p_mfc_dev *dev) | 87 | void s5p_mfc_final_pm(struct s5p_mfc_dev *dev) |
69 | { | 88 | { |
89 | if (dev->variant->version != MFC_VERSION_V6 && | ||
90 | pm->clock) { | ||
91 | clk_disable_unprepare(pm->clock); | ||
92 | clk_put(pm->clock); | ||
93 | } | ||
70 | clk_unprepare(pm->clock_gate); | 94 | clk_unprepare(pm->clock_gate); |
71 | clk_put(pm->clock_gate); | 95 | clk_put(pm->clock_gate); |
72 | #ifdef CONFIG_PM_RUNTIME | 96 | #ifdef CONFIG_PM_RUNTIME |
diff --git a/drivers/media/platform/s5p-tv/mixer_video.c b/drivers/media/platform/s5p-tv/mixer_video.c index 8a8dbc8fdfde..b4d2696501e4 100644 --- a/drivers/media/platform/s5p-tv/mixer_video.c +++ b/drivers/media/platform/s5p-tv/mixer_video.c | |||
@@ -1109,8 +1109,6 @@ struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev, | |||
1109 | .ioctl_ops = &mxr_ioctl_ops, | 1109 | .ioctl_ops = &mxr_ioctl_ops, |
1110 | }; | 1110 | }; |
1111 | strlcpy(layer->vfd.name, name, sizeof(layer->vfd.name)); | 1111 | strlcpy(layer->vfd.name, name, sizeof(layer->vfd.name)); |
1112 | /* let framework control PRIORITY */ | ||
1113 | set_bit(V4L2_FL_USE_FH_PRIO, &layer->vfd.flags); | ||
1114 | 1112 | ||
1115 | video_set_drvdata(&layer->vfd, layer); | 1113 | video_set_drvdata(&layer->vfd, layer); |
1116 | layer->vfd.lock = &layer->mutex; | 1114 | layer->vfd.lock = &layer->mutex; |
diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c index 744e43b480bc..8dc279d4d561 100644 --- a/drivers/media/platform/sh_veu.c +++ b/drivers/media/platform/sh_veu.c | |||
@@ -425,7 +425,6 @@ static int sh_veu_g_fmt(struct sh_veu_file *veu_file, struct v4l2_format *f) | |||
425 | pix->bytesperline = vfmt->bytesperline; | 425 | pix->bytesperline = vfmt->bytesperline; |
426 | pix->sizeimage = vfmt->bytesperline * pix->height * | 426 | pix->sizeimage = vfmt->bytesperline * pix->height * |
427 | vfmt->fmt->depth / vfmt->fmt->ydepth; | 427 | vfmt->fmt->depth / vfmt->fmt->ydepth; |
428 | pix->priv = 0; | ||
429 | dev_dbg(veu->dev, "%s(): type: %d, size %u @ %ux%u, fmt %x\n", __func__, | 428 | dev_dbg(veu->dev, "%s(): type: %d, size %u @ %ux%u, fmt %x\n", __func__, |
430 | f->type, pix->sizeimage, pix->width, pix->height, pix->pixelformat); | 429 | f->type, pix->sizeimage, pix->width, pix->height, pix->pixelformat); |
431 | 430 | ||
@@ -473,7 +472,6 @@ static int sh_veu_try_fmt(struct v4l2_format *f, const struct sh_veu_format *fmt | |||
473 | 472 | ||
474 | pix->pixelformat = fmt->fourcc; | 473 | pix->pixelformat = fmt->fourcc; |
475 | pix->colorspace = sh_veu_4cc2cspace(pix->pixelformat); | 474 | pix->colorspace = sh_veu_4cc2cspace(pix->pixelformat); |
476 | pix->priv = 0; | ||
477 | 475 | ||
478 | pr_debug("%s(): type: %d, size %u\n", __func__, f->type, pix->sizeimage); | 476 | pr_debug("%s(): type: %d, size %u\n", __func__, f->type, pix->sizeimage); |
479 | 477 | ||
diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig index af39c4665554..6540847f4e1d 100644 --- a/drivers/media/platform/soc_camera/Kconfig +++ b/drivers/media/platform/soc_camera/Kconfig | |||
@@ -17,19 +17,6 @@ config SOC_CAMERA_PLATFORM | |||
17 | help | 17 | help |
18 | This is a generic SoC camera platform driver, useful for testing | 18 | This is a generic SoC camera platform driver, useful for testing |
19 | 19 | ||
20 | config MX1_VIDEO | ||
21 | bool | ||
22 | |||
23 | config VIDEO_MX1 | ||
24 | tristate "i.MX1/i.MXL CMOS Sensor Interface driver" | ||
25 | depends on BROKEN | ||
26 | depends on VIDEO_DEV && ARCH_MX1 && SOC_CAMERA | ||
27 | select FIQ | ||
28 | select VIDEOBUF_DMA_CONTIG | ||
29 | select MX1_VIDEO | ||
30 | ---help--- | ||
31 | This is a v4l2 driver for the i.MX1/i.MXL CMOS Sensor Interface | ||
32 | |||
33 | config VIDEO_MX3 | 20 | config VIDEO_MX3 |
34 | tristate "i.MX3x Camera Sensor Interface driver" | 21 | tristate "i.MX3x Camera Sensor Interface driver" |
35 | depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA | 22 | depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA |
@@ -47,6 +34,7 @@ config VIDEO_PXA27x | |||
47 | config VIDEO_RCAR_VIN | 34 | config VIDEO_RCAR_VIN |
48 | tristate "R-Car Video Input (VIN) support" | 35 | tristate "R-Car Video Input (VIN) support" |
49 | depends on VIDEO_DEV && SOC_CAMERA | 36 | depends on VIDEO_DEV && SOC_CAMERA |
37 | depends on ARCH_SHMOBILE || COMPILE_TEST | ||
50 | select VIDEOBUF2_DMA_CONTIG | 38 | select VIDEOBUF2_DMA_CONTIG |
51 | select SOC_CAMERA_SCALE_CROP | 39 | select SOC_CAMERA_SCALE_CROP |
52 | ---help--- | 40 | ---help--- |
@@ -55,12 +43,14 @@ config VIDEO_RCAR_VIN | |||
55 | config VIDEO_SH_MOBILE_CSI2 | 43 | config VIDEO_SH_MOBILE_CSI2 |
56 | tristate "SuperH Mobile MIPI CSI-2 Interface driver" | 44 | tristate "SuperH Mobile MIPI CSI-2 Interface driver" |
57 | depends on VIDEO_DEV && SOC_CAMERA && HAVE_CLK | 45 | depends on VIDEO_DEV && SOC_CAMERA && HAVE_CLK |
46 | depends on ARCH_SHMOBILE || SUPERH || COMPILE_TEST | ||
58 | ---help--- | 47 | ---help--- |
59 | This is a v4l2 driver for the SuperH MIPI CSI-2 Interface | 48 | This is a v4l2 driver for the SuperH MIPI CSI-2 Interface |
60 | 49 | ||
61 | config VIDEO_SH_MOBILE_CEU | 50 | config VIDEO_SH_MOBILE_CEU |
62 | tristate "SuperH Mobile CEU Interface driver" | 51 | tristate "SuperH Mobile CEU Interface driver" |
63 | depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA && HAVE_CLK | 52 | depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA && HAVE_CLK |
53 | depends on ARCH_SHMOBILE || SUPERH || COMPILE_TEST | ||
64 | select VIDEOBUF2_DMA_CONTIG | 54 | select VIDEOBUF2_DMA_CONTIG |
65 | select SOC_CAMERA_SCALE_CROP | 55 | select SOC_CAMERA_SCALE_CROP |
66 | ---help--- | 56 | ---help--- |
@@ -76,7 +66,7 @@ config VIDEO_OMAP1 | |||
76 | 66 | ||
77 | config VIDEO_MX2 | 67 | config VIDEO_MX2 |
78 | tristate "i.MX27 Camera Sensor Interface driver" | 68 | tristate "i.MX27 Camera Sensor Interface driver" |
79 | depends on VIDEO_DEV && SOC_CAMERA && MACH_MX27 | 69 | depends on VIDEO_DEV && SOC_CAMERA && SOC_IMX27 |
80 | select VIDEOBUF2_DMA_CONTIG | 70 | select VIDEOBUF2_DMA_CONTIG |
81 | ---help--- | 71 | ---help--- |
82 | This is a v4l2 driver for the i.MX27 Camera Sensor Interface | 72 | This is a v4l2 driver for the i.MX27 Camera Sensor Interface |
diff --git a/drivers/media/platform/soc_camera/Makefile b/drivers/media/platform/soc_camera/Makefile index 8aed26d7a64d..2826382dc9f8 100644 --- a/drivers/media/platform/soc_camera/Makefile +++ b/drivers/media/platform/soc_camera/Makefile | |||
@@ -7,7 +7,6 @@ obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o | |||
7 | 7 | ||
8 | # soc-camera host drivers have to be linked after camera drivers | 8 | # soc-camera host drivers have to be linked after camera drivers |
9 | obj-$(CONFIG_VIDEO_ATMEL_ISI) += atmel-isi.o | 9 | obj-$(CONFIG_VIDEO_ATMEL_ISI) += atmel-isi.o |
10 | obj-$(CONFIG_VIDEO_MX1) += mx1_camera.o | ||
11 | obj-$(CONFIG_VIDEO_MX2) += mx2_camera.o | 10 | obj-$(CONFIG_VIDEO_MX2) += mx2_camera.o |
12 | obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o | 11 | obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o |
13 | obj-$(CONFIG_VIDEO_OMAP1) += omap1_camera.o | 12 | obj-$(CONFIG_VIDEO_OMAP1) += omap1_camera.o |
diff --git a/drivers/media/platform/soc_camera/atmel-isi.c b/drivers/media/platform/soc_camera/atmel-isi.c index 38c723aca438..3408b045b3f1 100644 --- a/drivers/media/platform/soc_camera/atmel-isi.c +++ b/drivers/media/platform/soc_camera/atmel-isi.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <media/atmel-isi.h> | 25 | #include <media/atmel-isi.h> |
26 | #include <media/soc_camera.h> | 26 | #include <media/soc_camera.h> |
27 | #include <media/soc_mediabus.h> | 27 | #include <media/soc_mediabus.h> |
28 | #include <media/v4l2-of.h> | ||
28 | #include <media/videobuf2-dma-contig.h> | 29 | #include <media/videobuf2-dma-contig.h> |
29 | 30 | ||
30 | #define MAX_BUFFER_NUM 32 | 31 | #define MAX_BUFFER_NUM 32 |
@@ -33,6 +34,7 @@ | |||
33 | #define VID_LIMIT_BYTES (16 * 1024 * 1024) | 34 | #define VID_LIMIT_BYTES (16 * 1024 * 1024) |
34 | #define MIN_FRAME_RATE 15 | 35 | #define MIN_FRAME_RATE 15 |
35 | #define FRAME_INTERVAL_MILLI_SEC (1000 / MIN_FRAME_RATE) | 36 | #define FRAME_INTERVAL_MILLI_SEC (1000 / MIN_FRAME_RATE) |
37 | #define ISI_DEFAULT_MCLK_FREQ 25000000 | ||
36 | 38 | ||
37 | /* Frame buffer descriptor */ | 39 | /* Frame buffer descriptor */ |
38 | struct fbd { | 40 | struct fbd { |
@@ -84,7 +86,7 @@ struct atmel_isi { | |||
84 | struct clk *mck; | 86 | struct clk *mck; |
85 | unsigned int irq; | 87 | unsigned int irq; |
86 | 88 | ||
87 | struct isi_platform_data *pdata; | 89 | struct isi_platform_data pdata; |
88 | u16 width_flags; /* max 12 bits */ | 90 | u16 width_flags; /* max 12 bits */ |
89 | 91 | ||
90 | struct list_head video_buffer_list; | 92 | struct list_head video_buffer_list; |
@@ -350,7 +352,7 @@ static void start_dma(struct atmel_isi *isi, struct frame_buffer *buffer) | |||
350 | 352 | ||
351 | cfg1 &= ~ISI_CFG1_FRATE_DIV_MASK; | 353 | cfg1 &= ~ISI_CFG1_FRATE_DIV_MASK; |
352 | /* Enable linked list */ | 354 | /* Enable linked list */ |
353 | cfg1 |= isi->pdata->frate | ISI_CFG1_DISCR; | 355 | cfg1 |= isi->pdata.frate | ISI_CFG1_DISCR; |
354 | 356 | ||
355 | /* Enable codec path and ISI */ | 357 | /* Enable codec path and ISI */ |
356 | ctrl = ISI_CTRL_CDC | ISI_CTRL_EN; | 358 | ctrl = ISI_CTRL_CDC | ISI_CTRL_EN; |
@@ -795,7 +797,7 @@ static int isi_camera_set_bus_param(struct soc_camera_device *icd) | |||
795 | /* Make choises, based on platform preferences */ | 797 | /* Make choises, based on platform preferences */ |
796 | if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) && | 798 | if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) && |
797 | (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) { | 799 | (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) { |
798 | if (isi->pdata->hsync_act_low) | 800 | if (isi->pdata.hsync_act_low) |
799 | common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH; | 801 | common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH; |
800 | else | 802 | else |
801 | common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW; | 803 | common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW; |
@@ -803,7 +805,7 @@ static int isi_camera_set_bus_param(struct soc_camera_device *icd) | |||
803 | 805 | ||
804 | if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) && | 806 | if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) && |
805 | (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) { | 807 | (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) { |
806 | if (isi->pdata->vsync_act_low) | 808 | if (isi->pdata.vsync_act_low) |
807 | common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH; | 809 | common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH; |
808 | else | 810 | else |
809 | common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW; | 811 | common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW; |
@@ -811,7 +813,7 @@ static int isi_camera_set_bus_param(struct soc_camera_device *icd) | |||
811 | 813 | ||
812 | if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) && | 814 | if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) && |
813 | (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) { | 815 | (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) { |
814 | if (isi->pdata->pclk_act_falling) | 816 | if (isi->pdata.pclk_act_falling) |
815 | common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING; | 817 | common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING; |
816 | else | 818 | else |
817 | common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING; | 819 | common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING; |
@@ -833,9 +835,9 @@ static int isi_camera_set_bus_param(struct soc_camera_device *icd) | |||
833 | if (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING) | 835 | if (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING) |
834 | cfg1 |= ISI_CFG1_PIXCLK_POL_ACTIVE_FALLING; | 836 | cfg1 |= ISI_CFG1_PIXCLK_POL_ACTIVE_FALLING; |
835 | 837 | ||
836 | if (isi->pdata->has_emb_sync) | 838 | if (isi->pdata.has_emb_sync) |
837 | cfg1 |= ISI_CFG1_EMB_SYNC; | 839 | cfg1 |= ISI_CFG1_EMB_SYNC; |
838 | if (isi->pdata->full_mode) | 840 | if (isi->pdata.full_mode) |
839 | cfg1 |= ISI_CFG1_FULL_MODE; | 841 | cfg1 |= ISI_CFG1_FULL_MODE; |
840 | 842 | ||
841 | isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS); | 843 | isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS); |
@@ -876,6 +878,51 @@ static int atmel_isi_remove(struct platform_device *pdev) | |||
876 | return 0; | 878 | return 0; |
877 | } | 879 | } |
878 | 880 | ||
881 | static int atmel_isi_probe_dt(struct atmel_isi *isi, | ||
882 | struct platform_device *pdev) | ||
883 | { | ||
884 | struct device_node *np= pdev->dev.of_node; | ||
885 | struct v4l2_of_endpoint ep; | ||
886 | int err; | ||
887 | |||
888 | /* Default settings for ISI */ | ||
889 | isi->pdata.full_mode = 1; | ||
890 | isi->pdata.mck_hz = ISI_DEFAULT_MCLK_FREQ; | ||
891 | isi->pdata.frate = ISI_CFG1_FRATE_CAPTURE_ALL; | ||
892 | |||
893 | np = of_graph_get_next_endpoint(np, NULL); | ||
894 | if (!np) { | ||
895 | dev_err(&pdev->dev, "Could not find the endpoint\n"); | ||
896 | return -EINVAL; | ||
897 | } | ||
898 | |||
899 | err = v4l2_of_parse_endpoint(np, &ep); | ||
900 | if (err) { | ||
901 | dev_err(&pdev->dev, "Could not parse the endpoint\n"); | ||
902 | goto err_probe_dt; | ||
903 | } | ||
904 | |||
905 | switch (ep.bus.parallel.bus_width) { | ||
906 | case 8: | ||
907 | isi->pdata.data_width_flags = ISI_DATAWIDTH_8; | ||
908 | break; | ||
909 | case 10: | ||
910 | isi->pdata.data_width_flags = | ||
911 | ISI_DATAWIDTH_8 | ISI_DATAWIDTH_10; | ||
912 | break; | ||
913 | default: | ||
914 | dev_err(&pdev->dev, "Unsupported bus width: %d\n", | ||
915 | ep.bus.parallel.bus_width); | ||
916 | err = -EINVAL; | ||
917 | goto err_probe_dt; | ||
918 | } | ||
919 | |||
920 | err_probe_dt: | ||
921 | of_node_put(np); | ||
922 | |||
923 | return err; | ||
924 | } | ||
925 | |||
879 | static int atmel_isi_probe(struct platform_device *pdev) | 926 | static int atmel_isi_probe(struct platform_device *pdev) |
880 | { | 927 | { |
881 | unsigned int irq; | 928 | unsigned int irq; |
@@ -887,7 +934,7 @@ static int atmel_isi_probe(struct platform_device *pdev) | |||
887 | struct isi_platform_data *pdata; | 934 | struct isi_platform_data *pdata; |
888 | 935 | ||
889 | pdata = dev->platform_data; | 936 | pdata = dev->platform_data; |
890 | if (!pdata || !pdata->data_width_flags) { | 937 | if ((!pdata || !pdata->data_width_flags) && !pdev->dev.of_node) { |
891 | dev_err(&pdev->dev, | 938 | dev_err(&pdev->dev, |
892 | "No config available for Atmel ISI\n"); | 939 | "No config available for Atmel ISI\n"); |
893 | return -EINVAL; | 940 | return -EINVAL; |
@@ -903,7 +950,14 @@ static int atmel_isi_probe(struct platform_device *pdev) | |||
903 | if (IS_ERR(isi->pclk)) | 950 | if (IS_ERR(isi->pclk)) |
904 | return PTR_ERR(isi->pclk); | 951 | return PTR_ERR(isi->pclk); |
905 | 952 | ||
906 | isi->pdata = pdata; | 953 | if (pdata) { |
954 | memcpy(&isi->pdata, pdata, sizeof(isi->pdata)); | ||
955 | } else { | ||
956 | ret = atmel_isi_probe_dt(isi, pdev); | ||
957 | if (ret) | ||
958 | return ret; | ||
959 | } | ||
960 | |||
907 | isi->active = NULL; | 961 | isi->active = NULL; |
908 | spin_lock_init(&isi->lock); | 962 | spin_lock_init(&isi->lock); |
909 | INIT_LIST_HEAD(&isi->video_buffer_list); | 963 | INIT_LIST_HEAD(&isi->video_buffer_list); |
@@ -919,7 +973,7 @@ static int atmel_isi_probe(struct platform_device *pdev) | |||
919 | /* Set ISI_MCK's frequency, it should be faster than pixel | 973 | /* Set ISI_MCK's frequency, it should be faster than pixel |
920 | * clock. | 974 | * clock. |
921 | */ | 975 | */ |
922 | ret = clk_set_rate(isi->mck, pdata->mck_hz); | 976 | ret = clk_set_rate(isi->mck, isi->pdata.mck_hz); |
923 | if (ret < 0) | 977 | if (ret < 0) |
924 | return ret; | 978 | return ret; |
925 | } | 979 | } |
@@ -953,9 +1007,9 @@ static int atmel_isi_probe(struct platform_device *pdev) | |||
953 | goto err_ioremap; | 1007 | goto err_ioremap; |
954 | } | 1008 | } |
955 | 1009 | ||
956 | if (pdata->data_width_flags & ISI_DATAWIDTH_8) | 1010 | if (isi->pdata.data_width_flags & ISI_DATAWIDTH_8) |
957 | isi->width_flags = 1 << 7; | 1011 | isi->width_flags = 1 << 7; |
958 | if (pdata->data_width_flags & ISI_DATAWIDTH_10) | 1012 | if (isi->pdata.data_width_flags & ISI_DATAWIDTH_10) |
959 | isi->width_flags |= 1 << 9; | 1013 | isi->width_flags |= 1 << 9; |
960 | 1014 | ||
961 | isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS); | 1015 | isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS); |
@@ -980,6 +1034,11 @@ static int atmel_isi_probe(struct platform_device *pdev) | |||
980 | soc_host->v4l2_dev.dev = &pdev->dev; | 1034 | soc_host->v4l2_dev.dev = &pdev->dev; |
981 | soc_host->nr = pdev->id; | 1035 | soc_host->nr = pdev->id; |
982 | 1036 | ||
1037 | if (isi->pdata.asd_sizes) { | ||
1038 | soc_host->asd = isi->pdata.asd; | ||
1039 | soc_host->asd_sizes = isi->pdata.asd_sizes; | ||
1040 | } | ||
1041 | |||
983 | ret = soc_camera_host_register(soc_host); | 1042 | ret = soc_camera_host_register(soc_host); |
984 | if (ret) { | 1043 | if (ret) { |
985 | dev_err(&pdev->dev, "Unable to register soc camera host\n"); | 1044 | dev_err(&pdev->dev, "Unable to register soc camera host\n"); |
@@ -1000,11 +1059,18 @@ err_alloc_ctx: | |||
1000 | return ret; | 1059 | return ret; |
1001 | } | 1060 | } |
1002 | 1061 | ||
1062 | static const struct of_device_id atmel_isi_of_match[] = { | ||
1063 | { .compatible = "atmel,at91sam9g45-isi" }, | ||
1064 | { } | ||
1065 | }; | ||
1066 | MODULE_DEVICE_TABLE(of, atmel_isi_of_match); | ||
1067 | |||
1003 | static struct platform_driver atmel_isi_driver = { | 1068 | static struct platform_driver atmel_isi_driver = { |
1004 | .remove = atmel_isi_remove, | 1069 | .remove = atmel_isi_remove, |
1005 | .driver = { | 1070 | .driver = { |
1006 | .name = "atmel_isi", | 1071 | .name = "atmel_isi", |
1007 | .owner = THIS_MODULE, | 1072 | .owner = THIS_MODULE, |
1073 | .of_match_table = of_match_ptr(atmel_isi_of_match), | ||
1008 | }, | 1074 | }, |
1009 | }; | 1075 | }; |
1010 | 1076 | ||
diff --git a/drivers/media/platform/soc_camera/mx1_camera.c b/drivers/media/platform/soc_camera/mx1_camera.c deleted file mode 100644 index fea3e61476ae..000000000000 --- a/drivers/media/platform/soc_camera/mx1_camera.c +++ /dev/null | |||
@@ -1,866 +0,0 @@ | |||
1 | /* | ||
2 | * V4L2 Driver for i.MXL/i.MXL camera (CSI) host | ||
3 | * | ||
4 | * Copyright (C) 2008, Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
5 | * Copyright (C) 2009, Darius Augulis <augulis.darius@gmail.com> | ||
6 | * | ||
7 | * Based on PXA SoC camera driver | ||
8 | * Copyright (C) 2006, Sascha Hauer, Pengutronix | ||
9 | * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/clk.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/device.h> | ||
19 | #include <linux/dma-mapping.h> | ||
20 | #include <linux/errno.h> | ||
21 | #include <linux/fs.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/io.h> | ||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/mm.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/moduleparam.h> | ||
29 | #include <linux/platform_device.h> | ||
30 | #include <linux/sched.h> | ||
31 | #include <linux/slab.h> | ||
32 | #include <linux/time.h> | ||
33 | #include <linux/videodev2.h> | ||
34 | |||
35 | #include <media/soc_camera.h> | ||
36 | #include <media/v4l2-common.h> | ||
37 | #include <media/v4l2-dev.h> | ||
38 | #include <media/videobuf-dma-contig.h> | ||
39 | #include <media/soc_mediabus.h> | ||
40 | |||
41 | #include <asm/dma.h> | ||
42 | #include <asm/fiq.h> | ||
43 | #include <mach/dma-mx1-mx2.h> | ||
44 | #include <mach/hardware.h> | ||
45 | #include <mach/irqs.h> | ||
46 | #include <linux/platform_data/camera-mx1.h> | ||
47 | |||
48 | /* | ||
49 | * CSI registers | ||
50 | */ | ||
51 | #define CSICR1 0x00 /* CSI Control Register 1 */ | ||
52 | #define CSISR 0x08 /* CSI Status Register */ | ||
53 | #define CSIRXR 0x10 /* CSI RxFIFO Register */ | ||
54 | |||
55 | #define CSICR1_RXFF_LEVEL(x) (((x) & 0x3) << 19) | ||
56 | #define CSICR1_SOF_POL (1 << 17) | ||
57 | #define CSICR1_SOF_INTEN (1 << 16) | ||
58 | #define CSICR1_MCLKDIV(x) (((x) & 0xf) << 12) | ||
59 | #define CSICR1_MCLKEN (1 << 9) | ||
60 | #define CSICR1_FCC (1 << 8) | ||
61 | #define CSICR1_BIG_ENDIAN (1 << 7) | ||
62 | #define CSICR1_CLR_RXFIFO (1 << 5) | ||
63 | #define CSICR1_GCLK_MODE (1 << 4) | ||
64 | #define CSICR1_DATA_POL (1 << 2) | ||
65 | #define CSICR1_REDGE (1 << 1) | ||
66 | #define CSICR1_EN (1 << 0) | ||
67 | |||
68 | #define CSISR_SFF_OR_INT (1 << 25) | ||
69 | #define CSISR_RFF_OR_INT (1 << 24) | ||
70 | #define CSISR_STATFF_INT (1 << 21) | ||
71 | #define CSISR_RXFF_INT (1 << 18) | ||
72 | #define CSISR_SOF_INT (1 << 16) | ||
73 | #define CSISR_DRDY (1 << 0) | ||
74 | |||
75 | #define DRIVER_VERSION "0.0.2" | ||
76 | #define DRIVER_NAME "mx1-camera" | ||
77 | |||
78 | #define CSI_IRQ_MASK (CSISR_SFF_OR_INT | CSISR_RFF_OR_INT | \ | ||
79 | CSISR_STATFF_INT | CSISR_RXFF_INT | CSISR_SOF_INT) | ||
80 | |||
81 | #define CSI_BUS_FLAGS (V4L2_MBUS_MASTER | V4L2_MBUS_HSYNC_ACTIVE_HIGH | \ | ||
82 | V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW | \ | ||
83 | V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING | \ | ||
84 | V4L2_MBUS_DATA_ACTIVE_HIGH | V4L2_MBUS_DATA_ACTIVE_LOW) | ||
85 | |||
86 | #define MAX_VIDEO_MEM 16 /* Video memory limit in megabytes */ | ||
87 | |||
88 | /* | ||
89 | * Structures | ||
90 | */ | ||
91 | |||
92 | /* buffer for one video frame */ | ||
93 | struct mx1_buffer { | ||
94 | /* common v4l buffer stuff -- must be first */ | ||
95 | struct videobuf_buffer vb; | ||
96 | enum v4l2_mbus_pixelcode code; | ||
97 | int inwork; | ||
98 | }; | ||
99 | |||
100 | /* | ||
101 | * i.MX1/i.MXL is only supposed to handle one camera on its Camera Sensor | ||
102 | * Interface. If anyone ever builds hardware to enable more than | ||
103 | * one camera, they will have to modify this driver too | ||
104 | */ | ||
105 | struct mx1_camera_dev { | ||
106 | struct soc_camera_host soc_host; | ||
107 | struct mx1_camera_pdata *pdata; | ||
108 | struct mx1_buffer *active; | ||
109 | struct resource *res; | ||
110 | struct clk *clk; | ||
111 | struct list_head capture; | ||
112 | |||
113 | void __iomem *base; | ||
114 | int dma_chan; | ||
115 | unsigned int irq; | ||
116 | unsigned long mclk; | ||
117 | |||
118 | spinlock_t lock; | ||
119 | }; | ||
120 | |||
121 | /* | ||
122 | * Videobuf operations | ||
123 | */ | ||
124 | static int mx1_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, | ||
125 | unsigned int *size) | ||
126 | { | ||
127 | struct soc_camera_device *icd = vq->priv_data; | ||
128 | |||
129 | *size = icd->sizeimage; | ||
130 | |||
131 | if (!*count) | ||
132 | *count = 32; | ||
133 | |||
134 | if (*size * *count > MAX_VIDEO_MEM * 1024 * 1024) | ||
135 | *count = (MAX_VIDEO_MEM * 1024 * 1024) / *size; | ||
136 | |||
137 | dev_dbg(icd->parent, "count=%d, size=%d\n", *count, *size); | ||
138 | |||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | static void free_buffer(struct videobuf_queue *vq, struct mx1_buffer *buf) | ||
143 | { | ||
144 | struct soc_camera_device *icd = vq->priv_data; | ||
145 | struct videobuf_buffer *vb = &buf->vb; | ||
146 | |||
147 | BUG_ON(in_interrupt()); | ||
148 | |||
149 | dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, | ||
150 | vb, vb->baddr, vb->bsize); | ||
151 | |||
152 | /* | ||
153 | * This waits until this buffer is out of danger, i.e., until it is no | ||
154 | * longer in STATE_QUEUED or STATE_ACTIVE | ||
155 | */ | ||
156 | videobuf_waiton(vq, vb, 0, 0); | ||
157 | videobuf_dma_contig_free(vq, vb); | ||
158 | |||
159 | vb->state = VIDEOBUF_NEEDS_INIT; | ||
160 | } | ||
161 | |||
162 | static int mx1_videobuf_prepare(struct videobuf_queue *vq, | ||
163 | struct videobuf_buffer *vb, enum v4l2_field field) | ||
164 | { | ||
165 | struct soc_camera_device *icd = vq->priv_data; | ||
166 | struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb); | ||
167 | int ret; | ||
168 | |||
169 | dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, | ||
170 | vb, vb->baddr, vb->bsize); | ||
171 | |||
172 | /* Added list head initialization on alloc */ | ||
173 | WARN_ON(!list_empty(&vb->queue)); | ||
174 | |||
175 | BUG_ON(NULL == icd->current_fmt); | ||
176 | |||
177 | /* | ||
178 | * I think, in buf_prepare you only have to protect global data, | ||
179 | * the actual buffer is yours | ||
180 | */ | ||
181 | buf->inwork = 1; | ||
182 | |||
183 | if (buf->code != icd->current_fmt->code || | ||
184 | vb->width != icd->user_width || | ||
185 | vb->height != icd->user_height || | ||
186 | vb->field != field) { | ||
187 | buf->code = icd->current_fmt->code; | ||
188 | vb->width = icd->user_width; | ||
189 | vb->height = icd->user_height; | ||
190 | vb->field = field; | ||
191 | vb->state = VIDEOBUF_NEEDS_INIT; | ||
192 | } | ||
193 | |||
194 | vb->size = icd->sizeimage; | ||
195 | if (0 != vb->baddr && vb->bsize < vb->size) { | ||
196 | ret = -EINVAL; | ||
197 | goto out; | ||
198 | } | ||
199 | |||
200 | if (vb->state == VIDEOBUF_NEEDS_INIT) { | ||
201 | ret = videobuf_iolock(vq, vb, NULL); | ||
202 | if (ret) | ||
203 | goto fail; | ||
204 | |||
205 | vb->state = VIDEOBUF_PREPARED; | ||
206 | } | ||
207 | |||
208 | buf->inwork = 0; | ||
209 | |||
210 | return 0; | ||
211 | |||
212 | fail: | ||
213 | free_buffer(vq, buf); | ||
214 | out: | ||
215 | buf->inwork = 0; | ||
216 | return ret; | ||
217 | } | ||
218 | |||
219 | static int mx1_camera_setup_dma(struct mx1_camera_dev *pcdev) | ||
220 | { | ||
221 | struct videobuf_buffer *vbuf = &pcdev->active->vb; | ||
222 | struct device *dev = pcdev->soc_host.icd->parent; | ||
223 | int ret; | ||
224 | |||
225 | if (unlikely(!pcdev->active)) { | ||
226 | dev_err(dev, "DMA End IRQ with no active buffer\n"); | ||
227 | return -EFAULT; | ||
228 | } | ||
229 | |||
230 | /* setup sg list for future DMA */ | ||
231 | ret = imx_dma_setup_single(pcdev->dma_chan, | ||
232 | videobuf_to_dma_contig(vbuf), | ||
233 | vbuf->size, pcdev->res->start + | ||
234 | CSIRXR, DMA_MODE_READ); | ||
235 | if (unlikely(ret)) | ||
236 | dev_err(dev, "Failed to setup DMA sg list\n"); | ||
237 | |||
238 | return ret; | ||
239 | } | ||
240 | |||
241 | /* Called under spinlock_irqsave(&pcdev->lock, ...) */ | ||
242 | static void mx1_videobuf_queue(struct videobuf_queue *vq, | ||
243 | struct videobuf_buffer *vb) | ||
244 | { | ||
245 | struct soc_camera_device *icd = vq->priv_data; | ||
246 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
247 | struct mx1_camera_dev *pcdev = ici->priv; | ||
248 | struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb); | ||
249 | |||
250 | dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, | ||
251 | vb, vb->baddr, vb->bsize); | ||
252 | |||
253 | list_add_tail(&vb->queue, &pcdev->capture); | ||
254 | |||
255 | vb->state = VIDEOBUF_ACTIVE; | ||
256 | |||
257 | if (!pcdev->active) { | ||
258 | pcdev->active = buf; | ||
259 | |||
260 | /* setup sg list for future DMA */ | ||
261 | if (!mx1_camera_setup_dma(pcdev)) { | ||
262 | unsigned int temp; | ||
263 | /* enable SOF irq */ | ||
264 | temp = __raw_readl(pcdev->base + CSICR1) | | ||
265 | CSICR1_SOF_INTEN; | ||
266 | __raw_writel(temp, pcdev->base + CSICR1); | ||
267 | } | ||
268 | } | ||
269 | } | ||
270 | |||
271 | static void mx1_videobuf_release(struct videobuf_queue *vq, | ||
272 | struct videobuf_buffer *vb) | ||
273 | { | ||
274 | struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb); | ||
275 | #ifdef DEBUG | ||
276 | struct soc_camera_device *icd = vq->priv_data; | ||
277 | struct device *dev = icd->parent; | ||
278 | |||
279 | dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, | ||
280 | vb, vb->baddr, vb->bsize); | ||
281 | |||
282 | switch (vb->state) { | ||
283 | case VIDEOBUF_ACTIVE: | ||
284 | dev_dbg(dev, "%s (active)\n", __func__); | ||
285 | break; | ||
286 | case VIDEOBUF_QUEUED: | ||
287 | dev_dbg(dev, "%s (queued)\n", __func__); | ||
288 | break; | ||
289 | case VIDEOBUF_PREPARED: | ||
290 | dev_dbg(dev, "%s (prepared)\n", __func__); | ||
291 | break; | ||
292 | default: | ||
293 | dev_dbg(dev, "%s (unknown)\n", __func__); | ||
294 | break; | ||
295 | } | ||
296 | #endif | ||
297 | |||
298 | free_buffer(vq, buf); | ||
299 | } | ||
300 | |||
301 | static void mx1_camera_wakeup(struct mx1_camera_dev *pcdev, | ||
302 | struct videobuf_buffer *vb, | ||
303 | struct mx1_buffer *buf) | ||
304 | { | ||
305 | /* _init is used to debug races, see comment in mx1_camera_reqbufs() */ | ||
306 | list_del_init(&vb->queue); | ||
307 | vb->state = VIDEOBUF_DONE; | ||
308 | v4l2_get_timestamp(&vb->ts); | ||
309 | vb->field_count++; | ||
310 | wake_up(&vb->done); | ||
311 | |||
312 | if (list_empty(&pcdev->capture)) { | ||
313 | pcdev->active = NULL; | ||
314 | return; | ||
315 | } | ||
316 | |||
317 | pcdev->active = list_entry(pcdev->capture.next, | ||
318 | struct mx1_buffer, vb.queue); | ||
319 | |||
320 | /* setup sg list for future DMA */ | ||
321 | if (likely(!mx1_camera_setup_dma(pcdev))) { | ||
322 | unsigned int temp; | ||
323 | |||
324 | /* enable SOF irq */ | ||
325 | temp = __raw_readl(pcdev->base + CSICR1) | CSICR1_SOF_INTEN; | ||
326 | __raw_writel(temp, pcdev->base + CSICR1); | ||
327 | } | ||
328 | } | ||
329 | |||
330 | static void mx1_camera_dma_irq(int channel, void *data) | ||
331 | { | ||
332 | struct mx1_camera_dev *pcdev = data; | ||
333 | struct device *dev = pcdev->soc_host.icd->parent; | ||
334 | struct mx1_buffer *buf; | ||
335 | struct videobuf_buffer *vb; | ||
336 | unsigned long flags; | ||
337 | |||
338 | spin_lock_irqsave(&pcdev->lock, flags); | ||
339 | |||
340 | imx_dma_disable(channel); | ||
341 | |||
342 | if (unlikely(!pcdev->active)) { | ||
343 | dev_err(dev, "DMA End IRQ with no active buffer\n"); | ||
344 | goto out; | ||
345 | } | ||
346 | |||
347 | vb = &pcdev->active->vb; | ||
348 | buf = container_of(vb, struct mx1_buffer, vb); | ||
349 | WARN_ON(buf->inwork || list_empty(&vb->queue)); | ||
350 | dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, | ||
351 | vb, vb->baddr, vb->bsize); | ||
352 | |||
353 | mx1_camera_wakeup(pcdev, vb, buf); | ||
354 | out: | ||
355 | spin_unlock_irqrestore(&pcdev->lock, flags); | ||
356 | } | ||
357 | |||
358 | static struct videobuf_queue_ops mx1_videobuf_ops = { | ||
359 | .buf_setup = mx1_videobuf_setup, | ||
360 | .buf_prepare = mx1_videobuf_prepare, | ||
361 | .buf_queue = mx1_videobuf_queue, | ||
362 | .buf_release = mx1_videobuf_release, | ||
363 | }; | ||
364 | |||
365 | static void mx1_camera_init_videobuf(struct videobuf_queue *q, | ||
366 | struct soc_camera_device *icd) | ||
367 | { | ||
368 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
369 | struct mx1_camera_dev *pcdev = ici->priv; | ||
370 | |||
371 | videobuf_queue_dma_contig_init(q, &mx1_videobuf_ops, icd->parent, | ||
372 | &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
373 | V4L2_FIELD_NONE, | ||
374 | sizeof(struct mx1_buffer), icd, &ici->host_lock); | ||
375 | } | ||
376 | |||
377 | static int mclk_get_divisor(struct mx1_camera_dev *pcdev) | ||
378 | { | ||
379 | unsigned int mclk = pcdev->mclk; | ||
380 | unsigned long div; | ||
381 | unsigned long lcdclk; | ||
382 | |||
383 | lcdclk = clk_get_rate(pcdev->clk); | ||
384 | |||
385 | /* | ||
386 | * We verify platform_mclk_10khz != 0, so if anyone breaks it, here | ||
387 | * they get a nice Oops | ||
388 | */ | ||
389 | div = (lcdclk + 2 * mclk - 1) / (2 * mclk) - 1; | ||
390 | |||
391 | dev_dbg(pcdev->soc_host.icd->parent, | ||
392 | "System clock %lukHz, target freq %dkHz, divisor %lu\n", | ||
393 | lcdclk / 1000, mclk / 1000, div); | ||
394 | |||
395 | return div; | ||
396 | } | ||
397 | |||
398 | static void mx1_camera_activate(struct mx1_camera_dev *pcdev) | ||
399 | { | ||
400 | unsigned int csicr1 = CSICR1_EN; | ||
401 | |||
402 | dev_dbg(pcdev->soc_host.v4l2_dev.dev, "Activate device\n"); | ||
403 | |||
404 | clk_prepare_enable(pcdev->clk); | ||
405 | |||
406 | /* enable CSI before doing anything else */ | ||
407 | __raw_writel(csicr1, pcdev->base + CSICR1); | ||
408 | |||
409 | csicr1 |= CSICR1_MCLKEN | CSICR1_FCC | CSICR1_GCLK_MODE; | ||
410 | csicr1 |= CSICR1_MCLKDIV(mclk_get_divisor(pcdev)); | ||
411 | csicr1 |= CSICR1_RXFF_LEVEL(2); /* 16 words */ | ||
412 | |||
413 | __raw_writel(csicr1, pcdev->base + CSICR1); | ||
414 | } | ||
415 | |||
416 | static void mx1_camera_deactivate(struct mx1_camera_dev *pcdev) | ||
417 | { | ||
418 | dev_dbg(pcdev->soc_host.v4l2_dev.dev, "Deactivate device\n"); | ||
419 | |||
420 | /* Disable all CSI interface */ | ||
421 | __raw_writel(0x00, pcdev->base + CSICR1); | ||
422 | |||
423 | clk_disable_unprepare(pcdev->clk); | ||
424 | } | ||
425 | |||
426 | static int mx1_camera_add_device(struct soc_camera_device *icd) | ||
427 | { | ||
428 | dev_info(icd->parent, "MX1 Camera driver attached to camera %d\n", | ||
429 | icd->devnum); | ||
430 | |||
431 | return 0; | ||
432 | } | ||
433 | |||
434 | static void mx1_camera_remove_device(struct soc_camera_device *icd) | ||
435 | { | ||
436 | dev_info(icd->parent, "MX1 Camera driver detached from camera %d\n", | ||
437 | icd->devnum); | ||
438 | } | ||
439 | |||
440 | /* | ||
441 | * The following two functions absolutely depend on the fact, that | ||
442 | * there can be only one camera on i.MX1/i.MXL camera sensor interface | ||
443 | */ | ||
444 | static int mx1_camera_clock_start(struct soc_camera_host *ici) | ||
445 | { | ||
446 | struct mx1_camera_dev *pcdev = ici->priv; | ||
447 | |||
448 | mx1_camera_activate(pcdev); | ||
449 | |||
450 | return 0; | ||
451 | } | ||
452 | |||
453 | static void mx1_camera_clock_stop(struct soc_camera_host *ici) | ||
454 | { | ||
455 | struct mx1_camera_dev *pcdev = ici->priv; | ||
456 | unsigned int csicr1; | ||
457 | |||
458 | /* disable interrupts */ | ||
459 | csicr1 = __raw_readl(pcdev->base + CSICR1) & ~CSI_IRQ_MASK; | ||
460 | __raw_writel(csicr1, pcdev->base + CSICR1); | ||
461 | |||
462 | /* Stop DMA engine */ | ||
463 | imx_dma_disable(pcdev->dma_chan); | ||
464 | |||
465 | mx1_camera_deactivate(pcdev); | ||
466 | } | ||
467 | |||
468 | static int mx1_camera_set_bus_param(struct soc_camera_device *icd) | ||
469 | { | ||
470 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
471 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
472 | struct mx1_camera_dev *pcdev = ici->priv; | ||
473 | struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; | ||
474 | unsigned long common_flags; | ||
475 | unsigned int csicr1; | ||
476 | int ret; | ||
477 | |||
478 | /* MX1 supports only 8bit buswidth */ | ||
479 | ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg); | ||
480 | if (!ret) { | ||
481 | common_flags = soc_mbus_config_compatible(&cfg, CSI_BUS_FLAGS); | ||
482 | if (!common_flags) { | ||
483 | dev_warn(icd->parent, | ||
484 | "Flags incompatible: camera 0x%x, host 0x%x\n", | ||
485 | cfg.flags, CSI_BUS_FLAGS); | ||
486 | return -EINVAL; | ||
487 | } | ||
488 | } else if (ret != -ENOIOCTLCMD) { | ||
489 | return ret; | ||
490 | } else { | ||
491 | common_flags = CSI_BUS_FLAGS; | ||
492 | } | ||
493 | |||
494 | /* Make choises, based on platform choice */ | ||
495 | if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) && | ||
496 | (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) { | ||
497 | if (!pcdev->pdata || | ||
498 | pcdev->pdata->flags & MX1_CAMERA_VSYNC_HIGH) | ||
499 | common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW; | ||
500 | else | ||
501 | common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH; | ||
502 | } | ||
503 | |||
504 | if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) && | ||
505 | (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) { | ||
506 | if (!pcdev->pdata || | ||
507 | pcdev->pdata->flags & MX1_CAMERA_PCLK_RISING) | ||
508 | common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING; | ||
509 | else | ||
510 | common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING; | ||
511 | } | ||
512 | |||
513 | if ((common_flags & V4L2_MBUS_DATA_ACTIVE_HIGH) && | ||
514 | (common_flags & V4L2_MBUS_DATA_ACTIVE_LOW)) { | ||
515 | if (!pcdev->pdata || | ||
516 | pcdev->pdata->flags & MX1_CAMERA_DATA_HIGH) | ||
517 | common_flags &= ~V4L2_MBUS_DATA_ACTIVE_LOW; | ||
518 | else | ||
519 | common_flags &= ~V4L2_MBUS_DATA_ACTIVE_HIGH; | ||
520 | } | ||
521 | |||
522 | cfg.flags = common_flags; | ||
523 | ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg); | ||
524 | if (ret < 0 && ret != -ENOIOCTLCMD) { | ||
525 | dev_dbg(icd->parent, "camera s_mbus_config(0x%lx) returned %d\n", | ||
526 | common_flags, ret); | ||
527 | return ret; | ||
528 | } | ||
529 | |||
530 | csicr1 = __raw_readl(pcdev->base + CSICR1); | ||
531 | |||
532 | if (common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) | ||
533 | csicr1 |= CSICR1_REDGE; | ||
534 | if (common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) | ||
535 | csicr1 |= CSICR1_SOF_POL; | ||
536 | if (common_flags & V4L2_MBUS_DATA_ACTIVE_LOW) | ||
537 | csicr1 |= CSICR1_DATA_POL; | ||
538 | |||
539 | __raw_writel(csicr1, pcdev->base + CSICR1); | ||
540 | |||
541 | return 0; | ||
542 | } | ||
543 | |||
544 | static int mx1_camera_set_fmt(struct soc_camera_device *icd, | ||
545 | struct v4l2_format *f) | ||
546 | { | ||
547 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
548 | const struct soc_camera_format_xlate *xlate; | ||
549 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
550 | struct v4l2_mbus_framefmt mf; | ||
551 | int ret, buswidth; | ||
552 | |||
553 | xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); | ||
554 | if (!xlate) { | ||
555 | dev_warn(icd->parent, "Format %x not found\n", | ||
556 | pix->pixelformat); | ||
557 | return -EINVAL; | ||
558 | } | ||
559 | |||
560 | buswidth = xlate->host_fmt->bits_per_sample; | ||
561 | if (buswidth > 8) { | ||
562 | dev_warn(icd->parent, | ||
563 | "bits-per-sample %d for format %x unsupported\n", | ||
564 | buswidth, pix->pixelformat); | ||
565 | return -EINVAL; | ||
566 | } | ||
567 | |||
568 | mf.width = pix->width; | ||
569 | mf.height = pix->height; | ||
570 | mf.field = pix->field; | ||
571 | mf.colorspace = pix->colorspace; | ||
572 | mf.code = xlate->code; | ||
573 | |||
574 | ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf); | ||
575 | if (ret < 0) | ||
576 | return ret; | ||
577 | |||
578 | if (mf.code != xlate->code) | ||
579 | return -EINVAL; | ||
580 | |||
581 | pix->width = mf.width; | ||
582 | pix->height = mf.height; | ||
583 | pix->field = mf.field; | ||
584 | pix->colorspace = mf.colorspace; | ||
585 | icd->current_fmt = xlate; | ||
586 | |||
587 | return ret; | ||
588 | } | ||
589 | |||
590 | static int mx1_camera_try_fmt(struct soc_camera_device *icd, | ||
591 | struct v4l2_format *f) | ||
592 | { | ||
593 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
594 | const struct soc_camera_format_xlate *xlate; | ||
595 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
596 | struct v4l2_mbus_framefmt mf; | ||
597 | int ret; | ||
598 | /* TODO: limit to mx1 hardware capabilities */ | ||
599 | |||
600 | xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); | ||
601 | if (!xlate) { | ||
602 | dev_warn(icd->parent, "Format %x not found\n", | ||
603 | pix->pixelformat); | ||
604 | return -EINVAL; | ||
605 | } | ||
606 | |||
607 | mf.width = pix->width; | ||
608 | mf.height = pix->height; | ||
609 | mf.field = pix->field; | ||
610 | mf.colorspace = pix->colorspace; | ||
611 | mf.code = xlate->code; | ||
612 | |||
613 | /* limit to sensor capabilities */ | ||
614 | ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf); | ||
615 | if (ret < 0) | ||
616 | return ret; | ||
617 | |||
618 | pix->width = mf.width; | ||
619 | pix->height = mf.height; | ||
620 | pix->field = mf.field; | ||
621 | pix->colorspace = mf.colorspace; | ||
622 | |||
623 | return 0; | ||
624 | } | ||
625 | |||
626 | static int mx1_camera_reqbufs(struct soc_camera_device *icd, | ||
627 | struct v4l2_requestbuffers *p) | ||
628 | { | ||
629 | int i; | ||
630 | |||
631 | /* | ||
632 | * This is for locking debugging only. I removed spinlocks and now I | ||
633 | * check whether .prepare is ever called on a linked buffer, or whether | ||
634 | * a dma IRQ can occur for an in-work or unlinked buffer. Until now | ||
635 | * it hadn't triggered | ||
636 | */ | ||
637 | for (i = 0; i < p->count; i++) { | ||
638 | struct mx1_buffer *buf = container_of(icd->vb_vidq.bufs[i], | ||
639 | struct mx1_buffer, vb); | ||
640 | buf->inwork = 0; | ||
641 | INIT_LIST_HEAD(&buf->vb.queue); | ||
642 | } | ||
643 | |||
644 | return 0; | ||
645 | } | ||
646 | |||
647 | static unsigned int mx1_camera_poll(struct file *file, poll_table *pt) | ||
648 | { | ||
649 | struct soc_camera_device *icd = file->private_data; | ||
650 | struct mx1_buffer *buf; | ||
651 | |||
652 | buf = list_entry(icd->vb_vidq.stream.next, struct mx1_buffer, | ||
653 | vb.stream); | ||
654 | |||
655 | poll_wait(file, &buf->vb.done, pt); | ||
656 | |||
657 | if (buf->vb.state == VIDEOBUF_DONE || | ||
658 | buf->vb.state == VIDEOBUF_ERROR) | ||
659 | return POLLIN | POLLRDNORM; | ||
660 | |||
661 | return 0; | ||
662 | } | ||
663 | |||
664 | static int mx1_camera_querycap(struct soc_camera_host *ici, | ||
665 | struct v4l2_capability *cap) | ||
666 | { | ||
667 | /* cap->name is set by the friendly caller:-> */ | ||
668 | strlcpy(cap->card, "i.MX1/i.MXL Camera", sizeof(cap->card)); | ||
669 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; | ||
670 | |||
671 | return 0; | ||
672 | } | ||
673 | |||
674 | static struct soc_camera_host_ops mx1_soc_camera_host_ops = { | ||
675 | .owner = THIS_MODULE, | ||
676 | .add = mx1_camera_add_device, | ||
677 | .remove = mx1_camera_remove_device, | ||
678 | .clock_start = mx1_camera_clock_start, | ||
679 | .clock_stop = mx1_camera_clock_stop, | ||
680 | .set_bus_param = mx1_camera_set_bus_param, | ||
681 | .set_fmt = mx1_camera_set_fmt, | ||
682 | .try_fmt = mx1_camera_try_fmt, | ||
683 | .init_videobuf = mx1_camera_init_videobuf, | ||
684 | .reqbufs = mx1_camera_reqbufs, | ||
685 | .poll = mx1_camera_poll, | ||
686 | .querycap = mx1_camera_querycap, | ||
687 | }; | ||
688 | |||
689 | static struct fiq_handler fh = { | ||
690 | .name = "csi_sof" | ||
691 | }; | ||
692 | |||
693 | static int __init mx1_camera_probe(struct platform_device *pdev) | ||
694 | { | ||
695 | struct mx1_camera_dev *pcdev; | ||
696 | struct resource *res; | ||
697 | struct pt_regs regs; | ||
698 | struct clk *clk; | ||
699 | void __iomem *base; | ||
700 | unsigned int irq; | ||
701 | int err = 0; | ||
702 | |||
703 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
704 | irq = platform_get_irq(pdev, 0); | ||
705 | if (!res || (int)irq <= 0) { | ||
706 | err = -ENODEV; | ||
707 | goto exit; | ||
708 | } | ||
709 | |||
710 | clk = clk_get(&pdev->dev, "csi_clk"); | ||
711 | if (IS_ERR(clk)) { | ||
712 | err = PTR_ERR(clk); | ||
713 | goto exit; | ||
714 | } | ||
715 | |||
716 | pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL); | ||
717 | if (!pcdev) { | ||
718 | dev_err(&pdev->dev, "Could not allocate pcdev\n"); | ||
719 | err = -ENOMEM; | ||
720 | goto exit_put_clk; | ||
721 | } | ||
722 | |||
723 | pcdev->res = res; | ||
724 | pcdev->clk = clk; | ||
725 | |||
726 | pcdev->pdata = pdev->dev.platform_data; | ||
727 | |||
728 | if (pcdev->pdata) | ||
729 | pcdev->mclk = pcdev->pdata->mclk_10khz * 10000; | ||
730 | |||
731 | if (!pcdev->mclk) { | ||
732 | dev_warn(&pdev->dev, | ||
733 | "mclk_10khz == 0! Please, fix your platform data. " | ||
734 | "Using default 20MHz\n"); | ||
735 | pcdev->mclk = 20000000; | ||
736 | } | ||
737 | |||
738 | INIT_LIST_HEAD(&pcdev->capture); | ||
739 | spin_lock_init(&pcdev->lock); | ||
740 | |||
741 | /* | ||
742 | * Request the regions. | ||
743 | */ | ||
744 | if (!request_mem_region(res->start, resource_size(res), DRIVER_NAME)) { | ||
745 | err = -EBUSY; | ||
746 | goto exit_kfree; | ||
747 | } | ||
748 | |||
749 | base = ioremap(res->start, resource_size(res)); | ||
750 | if (!base) { | ||
751 | err = -ENOMEM; | ||
752 | goto exit_release; | ||
753 | } | ||
754 | pcdev->irq = irq; | ||
755 | pcdev->base = base; | ||
756 | |||
757 | /* request dma */ | ||
758 | pcdev->dma_chan = imx_dma_request_by_prio(DRIVER_NAME, DMA_PRIO_HIGH); | ||
759 | if (pcdev->dma_chan < 0) { | ||
760 | dev_err(&pdev->dev, "Can't request DMA for MX1 CSI\n"); | ||
761 | err = -EBUSY; | ||
762 | goto exit_iounmap; | ||
763 | } | ||
764 | dev_dbg(&pdev->dev, "got DMA channel %d\n", pcdev->dma_chan); | ||
765 | |||
766 | imx_dma_setup_handlers(pcdev->dma_chan, mx1_camera_dma_irq, NULL, | ||
767 | pcdev); | ||
768 | |||
769 | imx_dma_config_channel(pcdev->dma_chan, IMX_DMA_TYPE_FIFO, | ||
770 | IMX_DMA_MEMSIZE_32, MX1_DMA_REQ_CSI_R, 0); | ||
771 | /* burst length : 16 words = 64 bytes */ | ||
772 | imx_dma_config_burstlen(pcdev->dma_chan, 0); | ||
773 | |||
774 | /* request irq */ | ||
775 | err = claim_fiq(&fh); | ||
776 | if (err) { | ||
777 | dev_err(&pdev->dev, "Camera interrupt register failed\n"); | ||
778 | goto exit_free_dma; | ||
779 | } | ||
780 | |||
781 | set_fiq_handler(&mx1_camera_sof_fiq_start, &mx1_camera_sof_fiq_end - | ||
782 | &mx1_camera_sof_fiq_start); | ||
783 | |||
784 | regs.ARM_r8 = (long)MX1_DMA_DIMR; | ||
785 | regs.ARM_r9 = (long)MX1_DMA_CCR(pcdev->dma_chan); | ||
786 | regs.ARM_r10 = (long)pcdev->base + CSICR1; | ||
787 | regs.ARM_fp = (long)pcdev->base + CSISR; | ||
788 | regs.ARM_sp = 1 << pcdev->dma_chan; | ||
789 | set_fiq_regs(®s); | ||
790 | |||
791 | mxc_set_irq_fiq(irq, 1); | ||
792 | enable_fiq(irq); | ||
793 | |||
794 | pcdev->soc_host.drv_name = DRIVER_NAME; | ||
795 | pcdev->soc_host.ops = &mx1_soc_camera_host_ops; | ||
796 | pcdev->soc_host.priv = pcdev; | ||
797 | pcdev->soc_host.v4l2_dev.dev = &pdev->dev; | ||
798 | pcdev->soc_host.nr = pdev->id; | ||
799 | err = soc_camera_host_register(&pcdev->soc_host); | ||
800 | if (err) | ||
801 | goto exit_free_irq; | ||
802 | |||
803 | dev_info(&pdev->dev, "MX1 Camera driver loaded\n"); | ||
804 | |||
805 | return 0; | ||
806 | |||
807 | exit_free_irq: | ||
808 | disable_fiq(irq); | ||
809 | mxc_set_irq_fiq(irq, 0); | ||
810 | release_fiq(&fh); | ||
811 | exit_free_dma: | ||
812 | imx_dma_free(pcdev->dma_chan); | ||
813 | exit_iounmap: | ||
814 | iounmap(base); | ||
815 | exit_release: | ||
816 | release_mem_region(res->start, resource_size(res)); | ||
817 | exit_kfree: | ||
818 | kfree(pcdev); | ||
819 | exit_put_clk: | ||
820 | clk_put(clk); | ||
821 | exit: | ||
822 | return err; | ||
823 | } | ||
824 | |||
825 | static int __exit mx1_camera_remove(struct platform_device *pdev) | ||
826 | { | ||
827 | struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); | ||
828 | struct mx1_camera_dev *pcdev = container_of(soc_host, | ||
829 | struct mx1_camera_dev, soc_host); | ||
830 | struct resource *res; | ||
831 | |||
832 | imx_dma_free(pcdev->dma_chan); | ||
833 | disable_fiq(pcdev->irq); | ||
834 | mxc_set_irq_fiq(pcdev->irq, 0); | ||
835 | release_fiq(&fh); | ||
836 | |||
837 | clk_put(pcdev->clk); | ||
838 | |||
839 | soc_camera_host_unregister(soc_host); | ||
840 | |||
841 | iounmap(pcdev->base); | ||
842 | |||
843 | res = pcdev->res; | ||
844 | release_mem_region(res->start, resource_size(res)); | ||
845 | |||
846 | kfree(pcdev); | ||
847 | |||
848 | dev_info(&pdev->dev, "MX1 Camera driver unloaded\n"); | ||
849 | |||
850 | return 0; | ||
851 | } | ||
852 | |||
853 | static struct platform_driver mx1_camera_driver = { | ||
854 | .driver = { | ||
855 | .name = DRIVER_NAME, | ||
856 | }, | ||
857 | .remove = __exit_p(mx1_camera_remove), | ||
858 | }; | ||
859 | |||
860 | module_platform_driver_probe(mx1_camera_driver, mx1_camera_probe); | ||
861 | |||
862 | MODULE_DESCRIPTION("i.MX1/i.MXL SoC Camera Host driver"); | ||
863 | MODULE_AUTHOR("Paulius Zaleckas <paulius.zaleckas@teltonika.lt>"); | ||
864 | MODULE_LICENSE("GPL v2"); | ||
865 | MODULE_VERSION(DRIVER_VERSION); | ||
866 | MODULE_ALIAS("platform:" DRIVER_NAME); | ||
diff --git a/drivers/media/platform/soc_camera/pxa_camera.c b/drivers/media/platform/soc_camera/pxa_camera.c index d4df305fcc18..64dc80ccd6f9 100644 --- a/drivers/media/platform/soc_camera/pxa_camera.c +++ b/drivers/media/platform/soc_camera/pxa_camera.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <media/videobuf-dma-sg.h> | 34 | #include <media/videobuf-dma-sg.h> |
35 | #include <media/soc_camera.h> | 35 | #include <media/soc_camera.h> |
36 | #include <media/soc_mediabus.h> | 36 | #include <media/soc_mediabus.h> |
37 | #include <media/v4l2-of.h> | ||
37 | 38 | ||
38 | #include <linux/videodev2.h> | 39 | #include <linux/videodev2.h> |
39 | 40 | ||
@@ -1650,6 +1651,68 @@ static struct soc_camera_host_ops pxa_soc_camera_host_ops = { | |||
1650 | .set_bus_param = pxa_camera_set_bus_param, | 1651 | .set_bus_param = pxa_camera_set_bus_param, |
1651 | }; | 1652 | }; |
1652 | 1653 | ||
1654 | static int pxa_camera_pdata_from_dt(struct device *dev, | ||
1655 | struct pxa_camera_dev *pcdev) | ||
1656 | { | ||
1657 | u32 mclk_rate; | ||
1658 | struct device_node *np = dev->of_node; | ||
1659 | struct v4l2_of_endpoint ep; | ||
1660 | int err = of_property_read_u32(np, "clock-frequency", | ||
1661 | &mclk_rate); | ||
1662 | if (!err) { | ||
1663 | pcdev->platform_flags |= PXA_CAMERA_MCLK_EN; | ||
1664 | pcdev->mclk = mclk_rate; | ||
1665 | } | ||
1666 | |||
1667 | np = of_graph_get_next_endpoint(np, NULL); | ||
1668 | if (!np) { | ||
1669 | dev_err(dev, "could not find endpoint\n"); | ||
1670 | return -EINVAL; | ||
1671 | } | ||
1672 | |||
1673 | err = v4l2_of_parse_endpoint(np, &ep); | ||
1674 | if (err) { | ||
1675 | dev_err(dev, "could not parse endpoint\n"); | ||
1676 | goto out; | ||
1677 | } | ||
1678 | |||
1679 | switch (ep.bus.parallel.bus_width) { | ||
1680 | case 4: | ||
1681 | pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_4; | ||
1682 | break; | ||
1683 | case 5: | ||
1684 | pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_5; | ||
1685 | break; | ||
1686 | case 8: | ||
1687 | pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_8; | ||
1688 | break; | ||
1689 | case 9: | ||
1690 | pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_9; | ||
1691 | break; | ||
1692 | case 10: | ||
1693 | pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_10; | ||
1694 | break; | ||
1695 | default: | ||
1696 | break; | ||
1697 | }; | ||
1698 | |||
1699 | if (ep.bus.parallel.flags & V4L2_MBUS_MASTER) | ||
1700 | pcdev->platform_flags |= PXA_CAMERA_MASTER; | ||
1701 | if (ep.bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) | ||
1702 | pcdev->platform_flags |= PXA_CAMERA_HSP; | ||
1703 | if (ep.bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) | ||
1704 | pcdev->platform_flags |= PXA_CAMERA_VSP; | ||
1705 | if (ep.bus.parallel.flags & V4L2_MBUS_PCLK_SAMPLE_RISING) | ||
1706 | pcdev->platform_flags |= PXA_CAMERA_PCLK_EN | PXA_CAMERA_PCP; | ||
1707 | if (ep.bus.parallel.flags & V4L2_MBUS_PCLK_SAMPLE_FALLING) | ||
1708 | pcdev->platform_flags |= PXA_CAMERA_PCLK_EN; | ||
1709 | |||
1710 | out: | ||
1711 | of_node_put(np); | ||
1712 | |||
1713 | return err; | ||
1714 | } | ||
1715 | |||
1653 | static int pxa_camera_probe(struct platform_device *pdev) | 1716 | static int pxa_camera_probe(struct platform_device *pdev) |
1654 | { | 1717 | { |
1655 | struct pxa_camera_dev *pcdev; | 1718 | struct pxa_camera_dev *pcdev; |
@@ -1676,7 +1739,15 @@ static int pxa_camera_probe(struct platform_device *pdev) | |||
1676 | pcdev->res = res; | 1739 | pcdev->res = res; |
1677 | 1740 | ||
1678 | pcdev->pdata = pdev->dev.platform_data; | 1741 | pcdev->pdata = pdev->dev.platform_data; |
1679 | pcdev->platform_flags = pcdev->pdata->flags; | 1742 | if (&pdev->dev.of_node && !pcdev->pdata) { |
1743 | err = pxa_camera_pdata_from_dt(&pdev->dev, pcdev); | ||
1744 | } else { | ||
1745 | pcdev->platform_flags = pcdev->pdata->flags; | ||
1746 | pcdev->mclk = pcdev->pdata->mclk_10khz * 10000; | ||
1747 | } | ||
1748 | if (err < 0) | ||
1749 | return err; | ||
1750 | |||
1680 | if (!(pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 | | 1751 | if (!(pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 | |
1681 | PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10))) { | 1752 | PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10))) { |
1682 | /* | 1753 | /* |
@@ -1693,7 +1764,6 @@ static int pxa_camera_probe(struct platform_device *pdev) | |||
1693 | pcdev->width_flags |= 1 << 8; | 1764 | pcdev->width_flags |= 1 << 8; |
1694 | if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10) | 1765 | if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10) |
1695 | pcdev->width_flags |= 1 << 9; | 1766 | pcdev->width_flags |= 1 << 9; |
1696 | pcdev->mclk = pcdev->pdata->mclk_10khz * 10000; | ||
1697 | if (!pcdev->mclk) { | 1767 | if (!pcdev->mclk) { |
1698 | dev_warn(&pdev->dev, | 1768 | dev_warn(&pdev->dev, |
1699 | "mclk == 0! Please, fix your platform data. " | 1769 | "mclk == 0! Please, fix your platform data. " |
@@ -1799,10 +1869,17 @@ static const struct dev_pm_ops pxa_camera_pm = { | |||
1799 | .resume = pxa_camera_resume, | 1869 | .resume = pxa_camera_resume, |
1800 | }; | 1870 | }; |
1801 | 1871 | ||
1872 | static const struct of_device_id pxa_camera_of_match[] = { | ||
1873 | { .compatible = "marvell,pxa270-qci", }, | ||
1874 | {}, | ||
1875 | }; | ||
1876 | MODULE_DEVICE_TABLE(of, pxa_camera_of_match); | ||
1877 | |||
1802 | static struct platform_driver pxa_camera_driver = { | 1878 | static struct platform_driver pxa_camera_driver = { |
1803 | .driver = { | 1879 | .driver = { |
1804 | .name = PXA_CAM_DRV_NAME, | 1880 | .name = PXA_CAM_DRV_NAME, |
1805 | .pm = &pxa_camera_pm, | 1881 | .pm = &pxa_camera_pm, |
1882 | .of_match_table = of_match_ptr(pxa_camera_of_match), | ||
1806 | }, | 1883 | }, |
1807 | .probe = pxa_camera_probe, | 1884 | .probe = pxa_camera_probe, |
1808 | .remove = pxa_camera_remove, | 1885 | .remove = pxa_camera_remove, |
diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c index e594230e84d3..85d579f65f52 100644 --- a/drivers/media/platform/soc_camera/rcar_vin.c +++ b/drivers/media/platform/soc_camera/rcar_vin.c | |||
@@ -19,6 +19,8 @@ | |||
19 | #include <linux/io.h> | 19 | #include <linux/io.h> |
20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/of.h> | ||
23 | #include <linux/of_device.h> | ||
22 | #include <linux/platform_data/camera-rcar.h> | 24 | #include <linux/platform_data/camera-rcar.h> |
23 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
24 | #include <linux/pm_runtime.h> | 26 | #include <linux/pm_runtime.h> |
@@ -31,6 +33,7 @@ | |||
31 | #include <media/v4l2-dev.h> | 33 | #include <media/v4l2-dev.h> |
32 | #include <media/v4l2-device.h> | 34 | #include <media/v4l2-device.h> |
33 | #include <media/v4l2-mediabus.h> | 35 | #include <media/v4l2-mediabus.h> |
36 | #include <media/v4l2-of.h> | ||
34 | #include <media/v4l2-subdev.h> | 37 | #include <media/v4l2-subdev.h> |
35 | #include <media/videobuf2-dma-contig.h> | 38 | #include <media/videobuf2-dma-contig.h> |
36 | 39 | ||
@@ -126,13 +129,13 @@ struct rcar_vin_priv { | |||
126 | int sequence; | 129 | int sequence; |
127 | /* State of the VIN module in capturing mode */ | 130 | /* State of the VIN module in capturing mode */ |
128 | enum rcar_vin_state state; | 131 | enum rcar_vin_state state; |
129 | struct rcar_vin_platform_data *pdata; | ||
130 | struct soc_camera_host ici; | 132 | struct soc_camera_host ici; |
131 | struct list_head capture; | 133 | struct list_head capture; |
132 | #define MAX_BUFFER_NUM 3 | 134 | #define MAX_BUFFER_NUM 3 |
133 | struct vb2_buffer *queue_buf[MAX_BUFFER_NUM]; | 135 | struct vb2_buffer *queue_buf[MAX_BUFFER_NUM]; |
134 | struct vb2_alloc_ctx *alloc_ctx; | 136 | struct vb2_alloc_ctx *alloc_ctx; |
135 | enum v4l2_field field; | 137 | enum v4l2_field field; |
138 | unsigned int pdata_flags; | ||
136 | unsigned int vb_count; | 139 | unsigned int vb_count; |
137 | unsigned int nr_hw_slots; | 140 | unsigned int nr_hw_slots; |
138 | bool request_to_stop; | 141 | bool request_to_stop; |
@@ -275,12 +278,12 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) | |||
275 | break; | 278 | break; |
276 | case V4L2_MBUS_FMT_YUYV8_2X8: | 279 | case V4L2_MBUS_FMT_YUYV8_2X8: |
277 | /* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */ | 280 | /* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */ |
278 | vnmc |= priv->pdata->flags & RCAR_VIN_BT656 ? | 281 | vnmc |= priv->pdata_flags & RCAR_VIN_BT656 ? |
279 | VNMC_INF_YUV8_BT656 : VNMC_INF_YUV8_BT601; | 282 | VNMC_INF_YUV8_BT656 : VNMC_INF_YUV8_BT601; |
280 | break; | 283 | break; |
281 | case V4L2_MBUS_FMT_YUYV10_2X10: | 284 | case V4L2_MBUS_FMT_YUYV10_2X10: |
282 | /* BT.656 10bit YCbCr422 or BT.601 10bit YCbCr422 */ | 285 | /* BT.656 10bit YCbCr422 or BT.601 10bit YCbCr422 */ |
283 | vnmc |= priv->pdata->flags & RCAR_VIN_BT656 ? | 286 | vnmc |= priv->pdata_flags & RCAR_VIN_BT656 ? |
284 | VNMC_INF_YUV10_BT656 : VNMC_INF_YUV10_BT601; | 287 | VNMC_INF_YUV10_BT656 : VNMC_INF_YUV10_BT601; |
285 | break; | 288 | break; |
286 | default: | 289 | default: |
@@ -797,7 +800,7 @@ static int rcar_vin_set_bus_param(struct soc_camera_device *icd) | |||
797 | /* Make choises, based on platform preferences */ | 800 | /* Make choises, based on platform preferences */ |
798 | if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) && | 801 | if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) && |
799 | (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) { | 802 | (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) { |
800 | if (priv->pdata->flags & RCAR_VIN_HSYNC_ACTIVE_LOW) | 803 | if (priv->pdata_flags & RCAR_VIN_HSYNC_ACTIVE_LOW) |
801 | common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH; | 804 | common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH; |
802 | else | 805 | else |
803 | common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW; | 806 | common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW; |
@@ -805,7 +808,7 @@ static int rcar_vin_set_bus_param(struct soc_camera_device *icd) | |||
805 | 808 | ||
806 | if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) && | 809 | if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) && |
807 | (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) { | 810 | (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) { |
808 | if (priv->pdata->flags & RCAR_VIN_VSYNC_ACTIVE_LOW) | 811 | if (priv->pdata_flags & RCAR_VIN_VSYNC_ACTIVE_LOW) |
809 | common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH; | 812 | common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH; |
810 | else | 813 | else |
811 | common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW; | 814 | common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW; |
@@ -1390,6 +1393,17 @@ static struct soc_camera_host_ops rcar_vin_host_ops = { | |||
1390 | .init_videobuf2 = rcar_vin_init_videobuf2, | 1393 | .init_videobuf2 = rcar_vin_init_videobuf2, |
1391 | }; | 1394 | }; |
1392 | 1395 | ||
1396 | #ifdef CONFIG_OF | ||
1397 | static struct of_device_id rcar_vin_of_table[] = { | ||
1398 | { .compatible = "renesas,vin-r8a7791", .data = (void *)RCAR_GEN2 }, | ||
1399 | { .compatible = "renesas,vin-r8a7790", .data = (void *)RCAR_GEN2 }, | ||
1400 | { .compatible = "renesas,vin-r8a7779", .data = (void *)RCAR_H1 }, | ||
1401 | { .compatible = "renesas,vin-r8a7778", .data = (void *)RCAR_M1 }, | ||
1402 | { }, | ||
1403 | }; | ||
1404 | MODULE_DEVICE_TABLE(of, rcar_vin_of_table); | ||
1405 | #endif | ||
1406 | |||
1393 | static struct platform_device_id rcar_vin_id_table[] = { | 1407 | static struct platform_device_id rcar_vin_id_table[] = { |
1394 | { "r8a7791-vin", RCAR_GEN2 }, | 1408 | { "r8a7791-vin", RCAR_GEN2 }, |
1395 | { "r8a7790-vin", RCAR_GEN2 }, | 1409 | { "r8a7790-vin", RCAR_GEN2 }, |
@@ -1402,15 +1416,52 @@ MODULE_DEVICE_TABLE(platform, rcar_vin_id_table); | |||
1402 | 1416 | ||
1403 | static int rcar_vin_probe(struct platform_device *pdev) | 1417 | static int rcar_vin_probe(struct platform_device *pdev) |
1404 | { | 1418 | { |
1419 | const struct of_device_id *match = NULL; | ||
1405 | struct rcar_vin_priv *priv; | 1420 | struct rcar_vin_priv *priv; |
1406 | struct resource *mem; | 1421 | struct resource *mem; |
1407 | struct rcar_vin_platform_data *pdata; | 1422 | struct rcar_vin_platform_data *pdata; |
1423 | unsigned int pdata_flags; | ||
1408 | int irq, ret; | 1424 | int irq, ret; |
1409 | 1425 | ||
1410 | pdata = pdev->dev.platform_data; | 1426 | if (pdev->dev.of_node) { |
1411 | if (!pdata || !pdata->flags) { | 1427 | struct v4l2_of_endpoint ep; |
1412 | dev_err(&pdev->dev, "platform data not set\n"); | 1428 | struct device_node *np; |
1413 | return -EINVAL; | 1429 | |
1430 | match = of_match_device(of_match_ptr(rcar_vin_of_table), | ||
1431 | &pdev->dev); | ||
1432 | |||
1433 | np = of_graph_get_next_endpoint(pdev->dev.of_node, NULL); | ||
1434 | if (!np) { | ||
1435 | dev_err(&pdev->dev, "could not find endpoint\n"); | ||
1436 | return -EINVAL; | ||
1437 | } | ||
1438 | |||
1439 | ret = v4l2_of_parse_endpoint(np, &ep); | ||
1440 | if (ret) { | ||
1441 | dev_err(&pdev->dev, "could not parse endpoint\n"); | ||
1442 | return ret; | ||
1443 | } | ||
1444 | |||
1445 | if (ep.bus_type == V4L2_MBUS_BT656) | ||
1446 | pdata_flags = RCAR_VIN_BT656; | ||
1447 | else { | ||
1448 | pdata_flags = 0; | ||
1449 | if (ep.bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW) | ||
1450 | pdata_flags |= RCAR_VIN_HSYNC_ACTIVE_LOW; | ||
1451 | if (ep.bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW) | ||
1452 | pdata_flags |= RCAR_VIN_VSYNC_ACTIVE_LOW; | ||
1453 | } | ||
1454 | |||
1455 | of_node_put(np); | ||
1456 | |||
1457 | dev_dbg(&pdev->dev, "pdata_flags = %08x\n", pdata_flags); | ||
1458 | } else { | ||
1459 | pdata = pdev->dev.platform_data; | ||
1460 | if (!pdata || !pdata->flags) { | ||
1461 | dev_err(&pdev->dev, "platform data not set\n"); | ||
1462 | return -EINVAL; | ||
1463 | } | ||
1464 | pdata_flags = pdata->flags; | ||
1414 | } | 1465 | } |
1415 | 1466 | ||
1416 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1467 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -1441,12 +1492,18 @@ static int rcar_vin_probe(struct platform_device *pdev) | |||
1441 | 1492 | ||
1442 | priv->ici.priv = priv; | 1493 | priv->ici.priv = priv; |
1443 | priv->ici.v4l2_dev.dev = &pdev->dev; | 1494 | priv->ici.v4l2_dev.dev = &pdev->dev; |
1444 | priv->ici.nr = pdev->id; | ||
1445 | priv->ici.drv_name = dev_name(&pdev->dev); | 1495 | priv->ici.drv_name = dev_name(&pdev->dev); |
1446 | priv->ici.ops = &rcar_vin_host_ops; | 1496 | priv->ici.ops = &rcar_vin_host_ops; |
1447 | 1497 | ||
1448 | priv->pdata = pdata; | 1498 | priv->pdata_flags = pdata_flags; |
1449 | priv->chip = pdev->id_entry->driver_data; | 1499 | if (!match) { |
1500 | priv->ici.nr = pdev->id; | ||
1501 | priv->chip = pdev->id_entry->driver_data; | ||
1502 | } else { | ||
1503 | priv->ici.nr = of_alias_get_id(pdev->dev.of_node, "vin"); | ||
1504 | priv->chip = (enum chip_id)match->data; | ||
1505 | }; | ||
1506 | |||
1450 | spin_lock_init(&priv->lock); | 1507 | spin_lock_init(&priv->lock); |
1451 | INIT_LIST_HEAD(&priv->capture); | 1508 | INIT_LIST_HEAD(&priv->capture); |
1452 | 1509 | ||
@@ -1487,6 +1544,7 @@ static struct platform_driver rcar_vin_driver = { | |||
1487 | .driver = { | 1544 | .driver = { |
1488 | .name = DRV_NAME, | 1545 | .name = DRV_NAME, |
1489 | .owner = THIS_MODULE, | 1546 | .owner = THIS_MODULE, |
1547 | .of_match_table = of_match_ptr(rcar_vin_of_table), | ||
1490 | }, | 1548 | }, |
1491 | .id_table = rcar_vin_id_table, | 1549 | .id_table = rcar_vin_id_table, |
1492 | }; | 1550 | }; |
diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index 7fec8cdaf095..f4308fed5431 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <media/v4l2-common.h> | 36 | #include <media/v4l2-common.h> |
37 | #include <media/v4l2-ioctl.h> | 37 | #include <media/v4l2-ioctl.h> |
38 | #include <media/v4l2-dev.h> | 38 | #include <media/v4l2-dev.h> |
39 | #include <media/v4l2-of.h> | ||
39 | #include <media/videobuf-core.h> | 40 | #include <media/videobuf-core.h> |
40 | #include <media/videobuf2-core.h> | 41 | #include <media/videobuf2-core.h> |
41 | 42 | ||
@@ -1524,14 +1525,14 @@ static int scan_async_group(struct soc_camera_host *ici, | |||
1524 | 1525 | ||
1525 | ret = soc_camera_dyn_pdev(&sdesc, sasc); | 1526 | ret = soc_camera_dyn_pdev(&sdesc, sasc); |
1526 | if (ret < 0) | 1527 | if (ret < 0) |
1527 | return ret; | 1528 | goto eallocpdev; |
1528 | 1529 | ||
1529 | sasc->sensor = &sasd->asd; | 1530 | sasc->sensor = &sasd->asd; |
1530 | 1531 | ||
1531 | icd = soc_camera_add_pdev(sasc); | 1532 | icd = soc_camera_add_pdev(sasc); |
1532 | if (!icd) { | 1533 | if (!icd) { |
1533 | platform_device_put(sasc->pdev); | 1534 | ret = -ENOMEM; |
1534 | return -ENOMEM; | 1535 | goto eaddpdev; |
1535 | } | 1536 | } |
1536 | 1537 | ||
1537 | sasc->notifier.subdevs = asd; | 1538 | sasc->notifier.subdevs = asd; |
@@ -1559,7 +1560,11 @@ static int scan_async_group(struct soc_camera_host *ici, | |||
1559 | v4l2_clk_unregister(icd->clk); | 1560 | v4l2_clk_unregister(icd->clk); |
1560 | eclkreg: | 1561 | eclkreg: |
1561 | icd->clk = NULL; | 1562 | icd->clk = NULL; |
1562 | platform_device_unregister(sasc->pdev); | 1563 | platform_device_del(sasc->pdev); |
1564 | eaddpdev: | ||
1565 | platform_device_put(sasc->pdev); | ||
1566 | eallocpdev: | ||
1567 | devm_kfree(ici->v4l2_dev.dev, sasc); | ||
1563 | dev_err(ici->v4l2_dev.dev, "group probe failed: %d\n", ret); | 1568 | dev_err(ici->v4l2_dev.dev, "group probe failed: %d\n", ret); |
1564 | 1569 | ||
1565 | return ret; | 1570 | return ret; |
@@ -1581,6 +1586,130 @@ static void scan_async_host(struct soc_camera_host *ici) | |||
1581 | #define scan_async_host(ici) do {} while (0) | 1586 | #define scan_async_host(ici) do {} while (0) |
1582 | #endif | 1587 | #endif |
1583 | 1588 | ||
1589 | #ifdef CONFIG_OF | ||
1590 | |||
1591 | struct soc_of_info { | ||
1592 | struct soc_camera_async_subdev sasd; | ||
1593 | struct soc_camera_async_client sasc; | ||
1594 | struct v4l2_async_subdev *subdev; | ||
1595 | }; | ||
1596 | |||
1597 | static int soc_of_bind(struct soc_camera_host *ici, | ||
1598 | struct device_node *ep, | ||
1599 | struct device_node *remote) | ||
1600 | { | ||
1601 | struct soc_camera_device *icd; | ||
1602 | struct soc_camera_desc sdesc = {.host_desc.bus_id = ici->nr,}; | ||
1603 | struct soc_camera_async_client *sasc; | ||
1604 | struct soc_of_info *info; | ||
1605 | struct i2c_client *client; | ||
1606 | char clk_name[V4L2_SUBDEV_NAME_SIZE]; | ||
1607 | int ret; | ||
1608 | |||
1609 | /* allocate a new subdev and add match info to it */ | ||
1610 | info = devm_kzalloc(ici->v4l2_dev.dev, sizeof(struct soc_of_info), | ||
1611 | GFP_KERNEL); | ||
1612 | if (!info) | ||
1613 | return -ENOMEM; | ||
1614 | |||
1615 | info->sasd.asd.match.of.node = remote; | ||
1616 | info->sasd.asd.match_type = V4L2_ASYNC_MATCH_OF; | ||
1617 | info->subdev = &info->sasd.asd; | ||
1618 | |||
1619 | /* Or shall this be managed by the soc-camera device? */ | ||
1620 | sasc = &info->sasc; | ||
1621 | |||
1622 | /* HACK: just need a != NULL */ | ||
1623 | sdesc.host_desc.board_info = ERR_PTR(-ENODATA); | ||
1624 | |||
1625 | ret = soc_camera_dyn_pdev(&sdesc, sasc); | ||
1626 | if (ret < 0) | ||
1627 | goto eallocpdev; | ||
1628 | |||
1629 | sasc->sensor = &info->sasd.asd; | ||
1630 | |||
1631 | icd = soc_camera_add_pdev(sasc); | ||
1632 | if (!icd) { | ||
1633 | ret = -ENOMEM; | ||
1634 | goto eaddpdev; | ||
1635 | } | ||
1636 | |||
1637 | sasc->notifier.subdevs = &info->subdev; | ||
1638 | sasc->notifier.num_subdevs = 1; | ||
1639 | sasc->notifier.bound = soc_camera_async_bound; | ||
1640 | sasc->notifier.unbind = soc_camera_async_unbind; | ||
1641 | sasc->notifier.complete = soc_camera_async_complete; | ||
1642 | |||
1643 | icd->sasc = sasc; | ||
1644 | icd->parent = ici->v4l2_dev.dev; | ||
1645 | |||
1646 | client = of_find_i2c_device_by_node(remote); | ||
1647 | |||
1648 | if (client) | ||
1649 | snprintf(clk_name, sizeof(clk_name), "%d-%04x", | ||
1650 | client->adapter->nr, client->addr); | ||
1651 | else | ||
1652 | snprintf(clk_name, sizeof(clk_name), "of-%s", | ||
1653 | of_node_full_name(remote)); | ||
1654 | |||
1655 | icd->clk = v4l2_clk_register(&soc_camera_clk_ops, clk_name, "mclk", icd); | ||
1656 | if (IS_ERR(icd->clk)) { | ||
1657 | ret = PTR_ERR(icd->clk); | ||
1658 | goto eclkreg; | ||
1659 | } | ||
1660 | |||
1661 | ret = v4l2_async_notifier_register(&ici->v4l2_dev, &sasc->notifier); | ||
1662 | if (!ret) | ||
1663 | return 0; | ||
1664 | eclkreg: | ||
1665 | icd->clk = NULL; | ||
1666 | platform_device_del(sasc->pdev); | ||
1667 | eaddpdev: | ||
1668 | platform_device_put(sasc->pdev); | ||
1669 | eallocpdev: | ||
1670 | devm_kfree(ici->v4l2_dev.dev, sasc); | ||
1671 | dev_err(ici->v4l2_dev.dev, "group probe failed: %d\n", ret); | ||
1672 | |||
1673 | return ret; | ||
1674 | } | ||
1675 | |||
1676 | static void scan_of_host(struct soc_camera_host *ici) | ||
1677 | { | ||
1678 | struct device *dev = ici->v4l2_dev.dev; | ||
1679 | struct device_node *np = dev->of_node; | ||
1680 | struct device_node *epn = NULL, *ren; | ||
1681 | unsigned int i; | ||
1682 | |||
1683 | for (i = 0; ; i++) { | ||
1684 | epn = of_graph_get_next_endpoint(np, epn); | ||
1685 | if (!epn) | ||
1686 | break; | ||
1687 | |||
1688 | ren = of_graph_get_remote_port(epn); | ||
1689 | if (!ren) { | ||
1690 | dev_notice(dev, "no remote for %s\n", | ||
1691 | of_node_full_name(epn)); | ||
1692 | continue; | ||
1693 | } | ||
1694 | |||
1695 | /* so we now have a remote node to connect */ | ||
1696 | if (!i) | ||
1697 | soc_of_bind(ici, epn, ren->parent); | ||
1698 | |||
1699 | of_node_put(epn); | ||
1700 | of_node_put(ren); | ||
1701 | |||
1702 | if (i) { | ||
1703 | dev_err(dev, "multiple subdevices aren't supported yet!\n"); | ||
1704 | break; | ||
1705 | } | ||
1706 | } | ||
1707 | } | ||
1708 | |||
1709 | #else | ||
1710 | static inline void scan_of_host(struct soc_camera_host *ici) { } | ||
1711 | #endif | ||
1712 | |||
1584 | /* Called during host-driver probe */ | 1713 | /* Called during host-driver probe */ |
1585 | static int soc_camera_probe(struct soc_camera_host *ici, | 1714 | static int soc_camera_probe(struct soc_camera_host *ici, |
1586 | struct soc_camera_device *icd) | 1715 | struct soc_camera_device *icd) |
@@ -1832,7 +1961,9 @@ int soc_camera_host_register(struct soc_camera_host *ici) | |||
1832 | mutex_init(&ici->host_lock); | 1961 | mutex_init(&ici->host_lock); |
1833 | mutex_init(&ici->clk_lock); | 1962 | mutex_init(&ici->clk_lock); |
1834 | 1963 | ||
1835 | if (ici->asd_sizes) | 1964 | if (ici->v4l2_dev.dev->of_node) |
1965 | scan_of_host(ici); | ||
1966 | else if (ici->asd_sizes) | ||
1836 | /* | 1967 | /* |
1837 | * No OF, host with a list of subdevices. Don't try to mix | 1968 | * No OF, host with a list of subdevices. Don't try to mix |
1838 | * modes by initialising some groups statically and some | 1969 | * modes by initialising some groups statically and some |
diff --git a/drivers/media/platform/vino.c b/drivers/media/platform/vino.c index 470d35336119..91d44ea16f27 100644 --- a/drivers/media/platform/vino.c +++ b/drivers/media/platform/vino.c | |||
@@ -3147,7 +3147,6 @@ static int vino_try_fmt_vid_cap(struct file *file, void *__fh, | |||
3147 | pf->colorspace = | 3147 | pf->colorspace = |
3148 | vino_data_formats[tempvcs.data_format].colorspace; | 3148 | vino_data_formats[tempvcs.data_format].colorspace; |
3149 | 3149 | ||
3150 | pf->priv = 0; | ||
3151 | return 0; | 3150 | return 0; |
3152 | } | 3151 | } |
3153 | 3152 | ||
@@ -3175,8 +3174,6 @@ static int vino_g_fmt_vid_cap(struct file *file, void *__fh, | |||
3175 | pf->colorspace = | 3174 | pf->colorspace = |
3176 | vino_data_formats[vcs->data_format].colorspace; | 3175 | vino_data_formats[vcs->data_format].colorspace; |
3177 | 3176 | ||
3178 | pf->priv = 0; | ||
3179 | |||
3180 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); | 3177 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); |
3181 | return 0; | 3178 | return 0; |
3182 | } | 3179 | } |
@@ -3219,8 +3216,6 @@ static int vino_s_fmt_vid_cap(struct file *file, void *__fh, | |||
3219 | pf->colorspace = | 3216 | pf->colorspace = |
3220 | vino_data_formats[vcs->data_format].colorspace; | 3217 | vino_data_formats[vcs->data_format].colorspace; |
3221 | 3218 | ||
3222 | pf->priv = 0; | ||
3223 | |||
3224 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); | 3219 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); |
3225 | return 0; | 3220 | return 0; |
3226 | } | 3221 | } |
diff --git a/drivers/media/platform/vivi.c b/drivers/media/platform/vivi.c index d00bf3df0f8a..80333714ffa7 100644 --- a/drivers/media/platform/vivi.c +++ b/drivers/media/platform/vivi.c | |||
@@ -648,13 +648,13 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf) | |||
648 | gen_text(dev, vbuf, line++ * 16, 16, str); | 648 | gen_text(dev, vbuf, line++ * 16, 16, str); |
649 | snprintf(str, sizeof(str), " int32 %d, int64 %lld, bitmask %08x ", | 649 | snprintf(str, sizeof(str), " int32 %d, int64 %lld, bitmask %08x ", |
650 | dev->int32->cur.val, | 650 | dev->int32->cur.val, |
651 | dev->int64->cur.val64, | 651 | *dev->int64->p_cur.p_s64, |
652 | dev->bitmask->cur.val); | 652 | dev->bitmask->cur.val); |
653 | gen_text(dev, vbuf, line++ * 16, 16, str); | 653 | gen_text(dev, vbuf, line++ * 16, 16, str); |
654 | snprintf(str, sizeof(str), " boolean %d, menu %s, string \"%s\" ", | 654 | snprintf(str, sizeof(str), " boolean %d, menu %s, string \"%s\" ", |
655 | dev->boolean->cur.val, | 655 | dev->boolean->cur.val, |
656 | dev->menu->qmenu[dev->menu->cur.val], | 656 | dev->menu->qmenu[dev->menu->cur.val], |
657 | dev->string->cur.string); | 657 | dev->string->p_cur.p_char); |
658 | gen_text(dev, vbuf, line++ * 16, 16, str); | 658 | gen_text(dev, vbuf, line++ * 16, 16, str); |
659 | snprintf(str, sizeof(str), " integer_menu %lld, value %d ", | 659 | snprintf(str, sizeof(str), " integer_menu %lld, value %d ", |
660 | dev->int_menu->qmenu_int[dev->int_menu->cur.val], | 660 | dev->int_menu->qmenu_int[dev->int_menu->cur.val], |
@@ -1014,7 +1014,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
1014 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | 1014 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; |
1015 | else | 1015 | else |
1016 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; | 1016 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; |
1017 | f->fmt.pix.priv = 0; | ||
1018 | return 0; | 1017 | return 0; |
1019 | } | 1018 | } |
1020 | 1019 | ||
@@ -1236,7 +1235,7 @@ static const struct v4l2_ctrl_config vivi_ctrl_int32 = { | |||
1236 | .id = VIVI_CID_CUSTOM_BASE + 2, | 1235 | .id = VIVI_CID_CUSTOM_BASE + 2, |
1237 | .name = "Integer 32 Bits", | 1236 | .name = "Integer 32 Bits", |
1238 | .type = V4L2_CTRL_TYPE_INTEGER, | 1237 | .type = V4L2_CTRL_TYPE_INTEGER, |
1239 | .min = 0x80000000, | 1238 | .min = -0x80000000LL, |
1240 | .max = 0x7fffffff, | 1239 | .max = 0x7fffffff, |
1241 | .step = 1, | 1240 | .step = 1, |
1242 | }; | 1241 | }; |
@@ -1246,6 +1245,9 @@ static const struct v4l2_ctrl_config vivi_ctrl_int64 = { | |||
1246 | .id = VIVI_CID_CUSTOM_BASE + 3, | 1245 | .id = VIVI_CID_CUSTOM_BASE + 3, |
1247 | .name = "Integer 64 Bits", | 1246 | .name = "Integer 64 Bits", |
1248 | .type = V4L2_CTRL_TYPE_INTEGER64, | 1247 | .type = V4L2_CTRL_TYPE_INTEGER64, |
1248 | .min = LLONG_MIN, | ||
1249 | .max = LLONG_MAX, | ||
1250 | .step = 1, | ||
1249 | }; | 1251 | }; |
1250 | 1252 | ||
1251 | static const char * const vivi_ctrl_menu_strings[] = { | 1253 | static const char * const vivi_ctrl_menu_strings[] = { |
@@ -1459,7 +1461,6 @@ static int __init vivi_create_instance(int inst) | |||
1459 | vfd->debug = debug; | 1461 | vfd->debug = debug; |
1460 | vfd->v4l2_dev = &dev->v4l2_dev; | 1462 | vfd->v4l2_dev = &dev->v4l2_dev; |
1461 | vfd->queue = q; | 1463 | vfd->queue = q; |
1462 | set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags); | ||
1463 | 1464 | ||
1464 | /* | 1465 | /* |
1465 | * Provide a mutex to v4l2 core. It will be used to protect | 1466 | * Provide a mutex to v4l2 core. It will be used to protect |
diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h index 6ca2cf20d545..12467191dff4 100644 --- a/drivers/media/platform/vsp1/vsp1.h +++ b/drivers/media/platform/vsp1/vsp1.h | |||
@@ -36,9 +36,9 @@ struct vsp1_rwpf; | |||
36 | struct vsp1_sru; | 36 | struct vsp1_sru; |
37 | struct vsp1_uds; | 37 | struct vsp1_uds; |
38 | 38 | ||
39 | #define VPS1_MAX_RPF 5 | 39 | #define VSP1_MAX_RPF 5 |
40 | #define VPS1_MAX_UDS 3 | 40 | #define VSP1_MAX_UDS 3 |
41 | #define VPS1_MAX_WPF 4 | 41 | #define VSP1_MAX_WPF 4 |
42 | 42 | ||
43 | struct vsp1_device { | 43 | struct vsp1_device { |
44 | struct device *dev; | 44 | struct device *dev; |
@@ -55,10 +55,10 @@ struct vsp1_device { | |||
55 | struct vsp1_hsit *hst; | 55 | struct vsp1_hsit *hst; |
56 | struct vsp1_lif *lif; | 56 | struct vsp1_lif *lif; |
57 | struct vsp1_lut *lut; | 57 | struct vsp1_lut *lut; |
58 | struct vsp1_rwpf *rpf[VPS1_MAX_RPF]; | 58 | struct vsp1_rwpf *rpf[VSP1_MAX_RPF]; |
59 | struct vsp1_sru *sru; | 59 | struct vsp1_sru *sru; |
60 | struct vsp1_uds *uds[VPS1_MAX_UDS]; | 60 | struct vsp1_uds *uds[VSP1_MAX_UDS]; |
61 | struct vsp1_rwpf *wpf[VPS1_MAX_WPF]; | 61 | struct vsp1_rwpf *wpf[VSP1_MAX_WPF]; |
62 | 62 | ||
63 | struct list_head entities; | 63 | struct list_head entities; |
64 | 64 | ||
@@ -66,7 +66,7 @@ struct vsp1_device { | |||
66 | struct media_device media_dev; | 66 | struct media_device media_dev; |
67 | }; | 67 | }; |
68 | 68 | ||
69 | struct vsp1_device *vsp1_device_get(struct vsp1_device *vsp1); | 69 | int vsp1_device_get(struct vsp1_device *vsp1); |
70 | void vsp1_device_put(struct vsp1_device *vsp1); | 70 | void vsp1_device_put(struct vsp1_device *vsp1); |
71 | 71 | ||
72 | static inline u32 vsp1_read(struct vsp1_device *vsp1, u32 reg) | 72 | static inline u32 vsp1_read(struct vsp1_device *vsp1, u32 reg) |
diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c index f80695480060..a0c1984c733e 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.c +++ b/drivers/media/platform/vsp1/vsp1_bru.c | |||
@@ -18,6 +18,7 @@ | |||
18 | 18 | ||
19 | #include "vsp1.h" | 19 | #include "vsp1.h" |
20 | #include "vsp1_bru.h" | 20 | #include "vsp1_bru.h" |
21 | #include "vsp1_rwpf.h" | ||
21 | 22 | ||
22 | #define BRU_MIN_SIZE 4U | 23 | #define BRU_MIN_SIZE 4U |
23 | #define BRU_MAX_SIZE 8190U | 24 | #define BRU_MAX_SIZE 8190U |
@@ -37,19 +38,47 @@ static inline void vsp1_bru_write(struct vsp1_bru *bru, u32 reg, u32 data) | |||
37 | } | 38 | } |
38 | 39 | ||
39 | /* ----------------------------------------------------------------------------- | 40 | /* ----------------------------------------------------------------------------- |
40 | * V4L2 Subdevice Core Operations | 41 | * Controls |
41 | */ | 42 | */ |
42 | 43 | ||
43 | static bool bru_is_input_enabled(struct vsp1_bru *bru, unsigned int input) | 44 | static int bru_s_ctrl(struct v4l2_ctrl *ctrl) |
44 | { | 45 | { |
45 | return media_entity_remote_pad(&bru->entity.pads[input]) != NULL; | 46 | struct vsp1_bru *bru = |
47 | container_of(ctrl->handler, struct vsp1_bru, ctrls); | ||
48 | |||
49 | if (!vsp1_entity_is_streaming(&bru->entity)) | ||
50 | return 0; | ||
51 | |||
52 | switch (ctrl->id) { | ||
53 | case V4L2_CID_BG_COLOR: | ||
54 | vsp1_bru_write(bru, VI6_BRU_VIRRPF_COL, ctrl->val | | ||
55 | (0xff << VI6_BRU_VIRRPF_COL_A_SHIFT)); | ||
56 | break; | ||
57 | } | ||
58 | |||
59 | return 0; | ||
46 | } | 60 | } |
47 | 61 | ||
62 | static const struct v4l2_ctrl_ops bru_ctrl_ops = { | ||
63 | .s_ctrl = bru_s_ctrl, | ||
64 | }; | ||
65 | |||
66 | /* ----------------------------------------------------------------------------- | ||
67 | * V4L2 Subdevice Core Operations | ||
68 | */ | ||
69 | |||
48 | static int bru_s_stream(struct v4l2_subdev *subdev, int enable) | 70 | static int bru_s_stream(struct v4l2_subdev *subdev, int enable) |
49 | { | 71 | { |
72 | struct vsp1_pipeline *pipe = to_vsp1_pipeline(&subdev->entity); | ||
50 | struct vsp1_bru *bru = to_bru(subdev); | 73 | struct vsp1_bru *bru = to_bru(subdev); |
51 | struct v4l2_mbus_framefmt *format; | 74 | struct v4l2_mbus_framefmt *format; |
75 | unsigned int flags; | ||
52 | unsigned int i; | 76 | unsigned int i; |
77 | int ret; | ||
78 | |||
79 | ret = vsp1_entity_set_streaming(&bru->entity, enable); | ||
80 | if (ret < 0) | ||
81 | return ret; | ||
53 | 82 | ||
54 | if (!enable) | 83 | if (!enable) |
55 | return 0; | 84 | return 0; |
@@ -62,18 +91,19 @@ static int bru_s_stream(struct v4l2_subdev *subdev, int enable) | |||
62 | * to sane default values for now. | 91 | * to sane default values for now. |
63 | */ | 92 | */ |
64 | 93 | ||
65 | /* Disable both color data normalization and dithering. */ | 94 | /* Disable dithering and enable color data normalization unless the |
66 | vsp1_bru_write(bru, VI6_BRU_INCTRL, 0); | 95 | * format at the pipeline output is premultiplied. |
67 | |||
68 | /* Set the background position to cover the whole output image and | ||
69 | * set its color to opaque black. | ||
70 | */ | 96 | */ |
97 | flags = pipe->output ? pipe->output->video.format.flags : 0; | ||
98 | vsp1_bru_write(bru, VI6_BRU_INCTRL, | ||
99 | flags & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA ? | ||
100 | 0 : VI6_BRU_INCTRL_NRM); | ||
101 | |||
102 | /* Set the background position to cover the whole output image. */ | ||
71 | vsp1_bru_write(bru, VI6_BRU_VIRRPF_SIZE, | 103 | vsp1_bru_write(bru, VI6_BRU_VIRRPF_SIZE, |
72 | (format->width << VI6_BRU_VIRRPF_SIZE_HSIZE_SHIFT) | | 104 | (format->width << VI6_BRU_VIRRPF_SIZE_HSIZE_SHIFT) | |
73 | (format->height << VI6_BRU_VIRRPF_SIZE_VSIZE_SHIFT)); | 105 | (format->height << VI6_BRU_VIRRPF_SIZE_VSIZE_SHIFT)); |
74 | vsp1_bru_write(bru, VI6_BRU_VIRRPF_LOC, 0); | 106 | vsp1_bru_write(bru, VI6_BRU_VIRRPF_LOC, 0); |
75 | vsp1_bru_write(bru, VI6_BRU_VIRRPF_COL, | ||
76 | 0xff << VI6_BRU_VIRRPF_COL_A_SHIFT); | ||
77 | 107 | ||
78 | /* Route BRU input 1 as SRC input to the ROP unit and configure the ROP | 108 | /* Route BRU input 1 as SRC input to the ROP unit and configure the ROP |
79 | * unit with a NOP operation to make BRU input 1 available as the | 109 | * unit with a NOP operation to make BRU input 1 available as the |
@@ -84,6 +114,7 @@ static int bru_s_stream(struct v4l2_subdev *subdev, int enable) | |||
84 | VI6_BRU_ROP_AROP(VI6_ROP_NOP)); | 114 | VI6_BRU_ROP_AROP(VI6_ROP_NOP)); |
85 | 115 | ||
86 | for (i = 0; i < 4; ++i) { | 116 | for (i = 0; i < 4; ++i) { |
117 | bool premultiplied = false; | ||
87 | u32 ctrl = 0; | 118 | u32 ctrl = 0; |
88 | 119 | ||
89 | /* Configure all Blend/ROP units corresponding to an enabled BRU | 120 | /* Configure all Blend/ROP units corresponding to an enabled BRU |
@@ -91,11 +122,15 @@ static int bru_s_stream(struct v4l2_subdev *subdev, int enable) | |||
91 | * disabled BRU inputs are used in ROP NOP mode to ignore the | 122 | * disabled BRU inputs are used in ROP NOP mode to ignore the |
92 | * SRC input. | 123 | * SRC input. |
93 | */ | 124 | */ |
94 | if (bru_is_input_enabled(bru, i)) | 125 | if (bru->inputs[i].rpf) { |
95 | ctrl |= VI6_BRU_CTRL_RBC; | 126 | ctrl |= VI6_BRU_CTRL_RBC; |
96 | else | 127 | |
128 | premultiplied = bru->inputs[i].rpf->video.format.flags | ||
129 | & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA; | ||
130 | } else { | ||
97 | ctrl |= VI6_BRU_CTRL_CROP(VI6_ROP_NOP) | 131 | ctrl |= VI6_BRU_CTRL_CROP(VI6_ROP_NOP) |
98 | | VI6_BRU_CTRL_AROP(VI6_ROP_NOP); | 132 | | VI6_BRU_CTRL_AROP(VI6_ROP_NOP); |
133 | } | ||
99 | 134 | ||
100 | /* Select the virtual RPF as the Blend/ROP unit A DST input to | 135 | /* Select the virtual RPF as the Blend/ROP unit A DST input to |
101 | * serve as a background color. | 136 | * serve as a background color. |
@@ -117,10 +152,18 @@ static int bru_s_stream(struct v4l2_subdev *subdev, int enable) | |||
117 | * | 152 | * |
118 | * DSTc = DSTc * (1 - SRCa) + SRCc * SRCa | 153 | * DSTc = DSTc * (1 - SRCa) + SRCc * SRCa |
119 | * DSTa = DSTa * (1 - SRCa) + SRCa | 154 | * DSTa = DSTa * (1 - SRCa) + SRCa |
155 | * | ||
156 | * when the SRC input isn't premultiplied, and to | ||
157 | * | ||
158 | * DSTc = DSTc * (1 - SRCa) + SRCc | ||
159 | * DSTa = DSTa * (1 - SRCa) + SRCa | ||
160 | * | ||
161 | * otherwise. | ||
120 | */ | 162 | */ |
121 | vsp1_bru_write(bru, VI6_BRU_BLD(i), | 163 | vsp1_bru_write(bru, VI6_BRU_BLD(i), |
122 | VI6_BRU_BLD_CCMDX_255_SRC_A | | 164 | VI6_BRU_BLD_CCMDX_255_SRC_A | |
123 | VI6_BRU_BLD_CCMDY_SRC_A | | 165 | (premultiplied ? VI6_BRU_BLD_CCMDY_COEFY : |
166 | VI6_BRU_BLD_CCMDY_SRC_A) | | ||
124 | VI6_BRU_BLD_ACMDX_255_SRC_A | | 167 | VI6_BRU_BLD_ACMDX_255_SRC_A | |
125 | VI6_BRU_BLD_ACMDY_COEFY | | 168 | VI6_BRU_BLD_ACMDY_COEFY | |
126 | (0xff << VI6_BRU_BLD_COEFY_SHIFT)); | 169 | (0xff << VI6_BRU_BLD_COEFY_SHIFT)); |
@@ -192,7 +235,7 @@ static struct v4l2_rect *bru_get_compose(struct vsp1_bru *bru, | |||
192 | case V4L2_SUBDEV_FORMAT_TRY: | 235 | case V4L2_SUBDEV_FORMAT_TRY: |
193 | return v4l2_subdev_get_try_crop(fh, pad); | 236 | return v4l2_subdev_get_try_crop(fh, pad); |
194 | case V4L2_SUBDEV_FORMAT_ACTIVE: | 237 | case V4L2_SUBDEV_FORMAT_ACTIVE: |
195 | return &bru->compose[pad]; | 238 | return &bru->inputs[pad].compose; |
196 | default: | 239 | default: |
197 | return NULL; | 240 | return NULL; |
198 | } | 241 | } |
@@ -391,5 +434,19 @@ struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1) | |||
391 | 434 | ||
392 | vsp1_entity_init_formats(subdev, NULL); | 435 | vsp1_entity_init_formats(subdev, NULL); |
393 | 436 | ||
437 | /* Initialize the control handler. */ | ||
438 | v4l2_ctrl_handler_init(&bru->ctrls, 1); | ||
439 | v4l2_ctrl_new_std(&bru->ctrls, &bru_ctrl_ops, V4L2_CID_BG_COLOR, | ||
440 | 0, 0xffffff, 1, 0); | ||
441 | |||
442 | bru->entity.subdev.ctrl_handler = &bru->ctrls; | ||
443 | |||
444 | if (bru->ctrls.error) { | ||
445 | dev_err(vsp1->dev, "bru: failed to initialize controls\n"); | ||
446 | ret = bru->ctrls.error; | ||
447 | vsp1_entity_destroy(&bru->entity); | ||
448 | return ERR_PTR(ret); | ||
449 | } | ||
450 | |||
394 | return bru; | 451 | return bru; |
395 | } | 452 | } |
diff --git a/drivers/media/platform/vsp1/vsp1_bru.h b/drivers/media/platform/vsp1/vsp1_bru.h index 37062704dbf6..16b1c6554911 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.h +++ b/drivers/media/platform/vsp1/vsp1_bru.h | |||
@@ -14,11 +14,13 @@ | |||
14 | #define __VSP1_BRU_H__ | 14 | #define __VSP1_BRU_H__ |
15 | 15 | ||
16 | #include <media/media-entity.h> | 16 | #include <media/media-entity.h> |
17 | #include <media/v4l2-ctrls.h> | ||
17 | #include <media/v4l2-subdev.h> | 18 | #include <media/v4l2-subdev.h> |
18 | 19 | ||
19 | #include "vsp1_entity.h" | 20 | #include "vsp1_entity.h" |
20 | 21 | ||
21 | struct vsp1_device; | 22 | struct vsp1_device; |
23 | struct vsp1_rwpf; | ||
22 | 24 | ||
23 | #define BRU_PAD_SINK(n) (n) | 25 | #define BRU_PAD_SINK(n) (n) |
24 | #define BRU_PAD_SOURCE 4 | 26 | #define BRU_PAD_SOURCE 4 |
@@ -26,7 +28,12 @@ struct vsp1_device; | |||
26 | struct vsp1_bru { | 28 | struct vsp1_bru { |
27 | struct vsp1_entity entity; | 29 | struct vsp1_entity entity; |
28 | 30 | ||
29 | struct v4l2_rect compose[4]; | 31 | struct v4l2_ctrl_handler ctrls; |
32 | |||
33 | struct { | ||
34 | struct vsp1_rwpf *rpf; | ||
35 | struct v4l2_rect compose; | ||
36 | } inputs[4]; | ||
30 | }; | 37 | }; |
31 | 38 | ||
32 | static inline struct vsp1_bru *to_bru(struct v4l2_subdev *subdev) | 39 | static inline struct vsp1_bru *to_bru(struct v4l2_subdev *subdev) |
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index c69ee0657f75..3e6601b5b4de 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c | |||
@@ -345,36 +345,32 @@ static int vsp1_device_init(struct vsp1_device *vsp1) | |||
345 | * Increment the VSP1 reference count and initialize the device if the first | 345 | * Increment the VSP1 reference count and initialize the device if the first |
346 | * reference is taken. | 346 | * reference is taken. |
347 | * | 347 | * |
348 | * Return a pointer to the VSP1 device or NULL if an error occurred. | 348 | * Return 0 on success or a negative error code otherwise. |
349 | */ | 349 | */ |
350 | struct vsp1_device *vsp1_device_get(struct vsp1_device *vsp1) | 350 | int vsp1_device_get(struct vsp1_device *vsp1) |
351 | { | 351 | { |
352 | struct vsp1_device *__vsp1 = vsp1; | 352 | int ret = 0; |
353 | int ret; | ||
354 | 353 | ||
355 | mutex_lock(&vsp1->lock); | 354 | mutex_lock(&vsp1->lock); |
356 | if (vsp1->ref_count > 0) | 355 | if (vsp1->ref_count > 0) |
357 | goto done; | 356 | goto done; |
358 | 357 | ||
359 | ret = clk_prepare_enable(vsp1->clock); | 358 | ret = clk_prepare_enable(vsp1->clock); |
360 | if (ret < 0) { | 359 | if (ret < 0) |
361 | __vsp1 = NULL; | ||
362 | goto done; | 360 | goto done; |
363 | } | ||
364 | 361 | ||
365 | ret = vsp1_device_init(vsp1); | 362 | ret = vsp1_device_init(vsp1); |
366 | if (ret < 0) { | 363 | if (ret < 0) { |
367 | clk_disable_unprepare(vsp1->clock); | 364 | clk_disable_unprepare(vsp1->clock); |
368 | __vsp1 = NULL; | ||
369 | goto done; | 365 | goto done; |
370 | } | 366 | } |
371 | 367 | ||
372 | done: | 368 | done: |
373 | if (__vsp1) | 369 | if (!ret) |
374 | vsp1->ref_count++; | 370 | vsp1->ref_count++; |
375 | 371 | ||
376 | mutex_unlock(&vsp1->lock); | 372 | mutex_unlock(&vsp1->lock); |
377 | return __vsp1; | 373 | return ret; |
378 | } | 374 | } |
379 | 375 | ||
380 | /* | 376 | /* |
@@ -440,19 +436,19 @@ static int vsp1_validate_platform_data(struct platform_device *pdev, | |||
440 | return -EINVAL; | 436 | return -EINVAL; |
441 | } | 437 | } |
442 | 438 | ||
443 | if (pdata->rpf_count <= 0 || pdata->rpf_count > VPS1_MAX_RPF) { | 439 | if (pdata->rpf_count <= 0 || pdata->rpf_count > VSP1_MAX_RPF) { |
444 | dev_err(&pdev->dev, "invalid number of RPF (%u)\n", | 440 | dev_err(&pdev->dev, "invalid number of RPF (%u)\n", |
445 | pdata->rpf_count); | 441 | pdata->rpf_count); |
446 | return -EINVAL; | 442 | return -EINVAL; |
447 | } | 443 | } |
448 | 444 | ||
449 | if (pdata->uds_count <= 0 || pdata->uds_count > VPS1_MAX_UDS) { | 445 | if (pdata->uds_count <= 0 || pdata->uds_count > VSP1_MAX_UDS) { |
450 | dev_err(&pdev->dev, "invalid number of UDS (%u)\n", | 446 | dev_err(&pdev->dev, "invalid number of UDS (%u)\n", |
451 | pdata->uds_count); | 447 | pdata->uds_count); |
452 | return -EINVAL; | 448 | return -EINVAL; |
453 | } | 449 | } |
454 | 450 | ||
455 | if (pdata->wpf_count <= 0 || pdata->wpf_count > VPS1_MAX_WPF) { | 451 | if (pdata->wpf_count <= 0 || pdata->wpf_count > VSP1_MAX_WPF) { |
456 | dev_err(&pdev->dev, "invalid number of WPF (%u)\n", | 452 | dev_err(&pdev->dev, "invalid number of WPF (%u)\n", |
457 | pdata->wpf_count); | 453 | pdata->wpf_count); |
458 | return -EINVAL; | 454 | return -EINVAL; |
diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 44167834285d..79af71d5e270 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c | |||
@@ -20,6 +20,42 @@ | |||
20 | 20 | ||
21 | #include "vsp1.h" | 21 | #include "vsp1.h" |
22 | #include "vsp1_entity.h" | 22 | #include "vsp1_entity.h" |
23 | #include "vsp1_video.h" | ||
24 | |||
25 | bool vsp1_entity_is_streaming(struct vsp1_entity *entity) | ||
26 | { | ||
27 | bool streaming; | ||
28 | |||
29 | mutex_lock(&entity->lock); | ||
30 | streaming = entity->streaming; | ||
31 | mutex_unlock(&entity->lock); | ||
32 | |||
33 | return streaming; | ||
34 | } | ||
35 | |||
36 | int vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming) | ||
37 | { | ||
38 | int ret; | ||
39 | |||
40 | mutex_lock(&entity->lock); | ||
41 | entity->streaming = streaming; | ||
42 | mutex_unlock(&entity->lock); | ||
43 | |||
44 | if (!streaming) | ||
45 | return 0; | ||
46 | |||
47 | if (!entity->subdev.ctrl_handler) | ||
48 | return 0; | ||
49 | |||
50 | ret = v4l2_ctrl_handler_setup(entity->subdev.ctrl_handler); | ||
51 | if (ret < 0) { | ||
52 | mutex_lock(&entity->lock); | ||
53 | entity->streaming = false; | ||
54 | mutex_unlock(&entity->lock); | ||
55 | } | ||
56 | |||
57 | return ret; | ||
58 | } | ||
23 | 59 | ||
24 | /* ----------------------------------------------------------------------------- | 60 | /* ----------------------------------------------------------------------------- |
25 | * V4L2 Subdevice Operations | 61 | * V4L2 Subdevice Operations |
@@ -157,6 +193,8 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity, | |||
157 | if (i == ARRAY_SIZE(vsp1_routes)) | 193 | if (i == ARRAY_SIZE(vsp1_routes)) |
158 | return -EINVAL; | 194 | return -EINVAL; |
159 | 195 | ||
196 | mutex_init(&entity->lock); | ||
197 | |||
160 | entity->vsp1 = vsp1; | 198 | entity->vsp1 = vsp1; |
161 | entity->source_pad = num_pads - 1; | 199 | entity->source_pad = num_pads - 1; |
162 | 200 | ||
@@ -185,7 +223,11 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity, | |||
185 | 223 | ||
186 | void vsp1_entity_destroy(struct vsp1_entity *entity) | 224 | void vsp1_entity_destroy(struct vsp1_entity *entity) |
187 | { | 225 | { |
226 | if (entity->video) | ||
227 | vsp1_video_cleanup(entity->video); | ||
188 | if (entity->subdev.ctrl_handler) | 228 | if (entity->subdev.ctrl_handler) |
189 | v4l2_ctrl_handler_free(entity->subdev.ctrl_handler); | 229 | v4l2_ctrl_handler_free(entity->subdev.ctrl_handler); |
190 | media_entity_cleanup(&entity->subdev.entity); | 230 | media_entity_cleanup(&entity->subdev.entity); |
231 | |||
232 | mutex_destroy(&entity->lock); | ||
191 | } | 233 | } |
diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index 7afbd8a7ba66..aa20aaa58208 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h | |||
@@ -14,10 +14,12 @@ | |||
14 | #define __VSP1_ENTITY_H__ | 14 | #define __VSP1_ENTITY_H__ |
15 | 15 | ||
16 | #include <linux/list.h> | 16 | #include <linux/list.h> |
17 | #include <linux/mutex.h> | ||
17 | 18 | ||
18 | #include <media/v4l2-subdev.h> | 19 | #include <media/v4l2-subdev.h> |
19 | 20 | ||
20 | struct vsp1_device; | 21 | struct vsp1_device; |
22 | struct vsp1_video; | ||
21 | 23 | ||
22 | enum vsp1_entity_type { | 24 | enum vsp1_entity_type { |
23 | VSP1_ENTITY_BRU, | 25 | VSP1_ENTITY_BRU, |
@@ -68,6 +70,11 @@ struct vsp1_entity { | |||
68 | 70 | ||
69 | struct v4l2_subdev subdev; | 71 | struct v4l2_subdev subdev; |
70 | struct v4l2_mbus_framefmt *formats; | 72 | struct v4l2_mbus_framefmt *formats; |
73 | |||
74 | struct vsp1_video *video; | ||
75 | |||
76 | struct mutex lock; /* Protects the streaming field */ | ||
77 | bool streaming; | ||
71 | }; | 78 | }; |
72 | 79 | ||
73 | static inline struct vsp1_entity *to_vsp1_entity(struct v4l2_subdev *subdev) | 80 | static inline struct vsp1_entity *to_vsp1_entity(struct v4l2_subdev *subdev) |
@@ -89,4 +96,7 @@ vsp1_entity_get_pad_format(struct vsp1_entity *entity, | |||
89 | void vsp1_entity_init_formats(struct v4l2_subdev *subdev, | 96 | void vsp1_entity_init_formats(struct v4l2_subdev *subdev, |
90 | struct v4l2_subdev_fh *fh); | 97 | struct v4l2_subdev_fh *fh); |
91 | 98 | ||
99 | bool vsp1_entity_is_streaming(struct vsp1_entity *entity); | ||
100 | int vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming); | ||
101 | |||
92 | #endif /* __VSP1_ENTITY_H__ */ | 102 | #endif /* __VSP1_ENTITY_H__ */ |
diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h index 3e74b44286f6..55f163d32d15 100644 --- a/drivers/media/platform/vsp1/vsp1_regs.h +++ b/drivers/media/platform/vsp1/vsp1_regs.h | |||
@@ -336,7 +336,9 @@ | |||
336 | */ | 336 | */ |
337 | 337 | ||
338 | #define VI6_SRU_CTRL0 0x2200 | 338 | #define VI6_SRU_CTRL0 0x2200 |
339 | #define VI6_SRU_CTRL0_PARAM0_MASK (0x1ff << 16) | ||
339 | #define VI6_SRU_CTRL0_PARAM0_SHIFT 16 | 340 | #define VI6_SRU_CTRL0_PARAM0_SHIFT 16 |
341 | #define VI6_SRU_CTRL0_PARAM1_MASK (0x1f << 8) | ||
340 | #define VI6_SRU_CTRL0_PARAM1_SHIFT 8 | 342 | #define VI6_SRU_CTRL0_PARAM1_SHIFT 8 |
341 | #define VI6_SRU_CTRL0_MODE_UPSCALE (4 << 4) | 343 | #define VI6_SRU_CTRL0_MODE_UPSCALE (4 << 4) |
342 | #define VI6_SRU_CTRL0_PARAM2 (1 << 3) | 344 | #define VI6_SRU_CTRL0_PARAM2 (1 << 3) |
diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index c3d98642a4aa..d14d26b718ef 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c | |||
@@ -39,6 +39,36 @@ static inline void vsp1_rpf_write(struct vsp1_rwpf *rpf, u32 reg, u32 data) | |||
39 | } | 39 | } |
40 | 40 | ||
41 | /* ----------------------------------------------------------------------------- | 41 | /* ----------------------------------------------------------------------------- |
42 | * Controls | ||
43 | */ | ||
44 | |||
45 | static int rpf_s_ctrl(struct v4l2_ctrl *ctrl) | ||
46 | { | ||
47 | struct vsp1_rwpf *rpf = | ||
48 | container_of(ctrl->handler, struct vsp1_rwpf, ctrls); | ||
49 | struct vsp1_pipeline *pipe; | ||
50 | |||
51 | if (!vsp1_entity_is_streaming(&rpf->entity)) | ||
52 | return 0; | ||
53 | |||
54 | switch (ctrl->id) { | ||
55 | case V4L2_CID_ALPHA_COMPONENT: | ||
56 | vsp1_rpf_write(rpf, VI6_RPF_VRTCOL_SET, | ||
57 | ctrl->val << VI6_RPF_VRTCOL_SET_LAYA_SHIFT); | ||
58 | |||
59 | pipe = to_vsp1_pipeline(&rpf->entity.subdev.entity); | ||
60 | vsp1_pipeline_propagate_alpha(pipe, &rpf->entity, ctrl->val); | ||
61 | break; | ||
62 | } | ||
63 | |||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | static const struct v4l2_ctrl_ops rpf_ctrl_ops = { | ||
68 | .s_ctrl = rpf_s_ctrl, | ||
69 | }; | ||
70 | |||
71 | /* ----------------------------------------------------------------------------- | ||
42 | * V4L2 Subdevice Core Operations | 72 | * V4L2 Subdevice Core Operations |
43 | */ | 73 | */ |
44 | 74 | ||
@@ -50,6 +80,11 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable) | |||
50 | const struct v4l2_rect *crop = &rpf->crop; | 80 | const struct v4l2_rect *crop = &rpf->crop; |
51 | u32 pstride; | 81 | u32 pstride; |
52 | u32 infmt; | 82 | u32 infmt; |
83 | int ret; | ||
84 | |||
85 | ret = vsp1_entity_set_streaming(&rpf->entity, enable); | ||
86 | if (ret < 0) | ||
87 | return ret; | ||
53 | 88 | ||
54 | if (!enable) | 89 | if (!enable) |
55 | return 0; | 90 | return 0; |
@@ -101,12 +136,13 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable) | |||
101 | (rpf->location.left << VI6_RPF_LOC_HCOORD_SHIFT) | | 136 | (rpf->location.left << VI6_RPF_LOC_HCOORD_SHIFT) | |
102 | (rpf->location.top << VI6_RPF_LOC_VCOORD_SHIFT)); | 137 | (rpf->location.top << VI6_RPF_LOC_VCOORD_SHIFT)); |
103 | 138 | ||
104 | /* Disable alpha, mask and color key. Set the alpha channel to a fixed | 139 | /* Use the alpha channel (extended to 8 bits) when available or an |
105 | * value of 255. | 140 | * alpha value set through the V4L2_CID_ALPHA_COMPONENT control |
141 | * otherwise. Disable color keying. | ||
106 | */ | 142 | */ |
107 | vsp1_rpf_write(rpf, VI6_RPF_ALPH_SEL, VI6_RPF_ALPH_SEL_ASEL_FIXED); | 143 | vsp1_rpf_write(rpf, VI6_RPF_ALPH_SEL, VI6_RPF_ALPH_SEL_AEXT_EXT | |
108 | vsp1_rpf_write(rpf, VI6_RPF_VRTCOL_SET, | 144 | (fmtinfo->alpha ? VI6_RPF_ALPH_SEL_ASEL_PACKED |
109 | 255 << VI6_RPF_VRTCOL_SET_LAYA_SHIFT); | 145 | : VI6_RPF_ALPH_SEL_ASEL_FIXED)); |
110 | vsp1_rpf_write(rpf, VI6_RPF_MSK_CTRL, 0); | 146 | vsp1_rpf_write(rpf, VI6_RPF_MSK_CTRL, 0); |
111 | vsp1_rpf_write(rpf, VI6_RPF_CKEY_CTRL, 0); | 147 | vsp1_rpf_write(rpf, VI6_RPF_CKEY_CTRL, 0); |
112 | 148 | ||
@@ -196,6 +232,20 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index) | |||
196 | 232 | ||
197 | vsp1_entity_init_formats(subdev, NULL); | 233 | vsp1_entity_init_formats(subdev, NULL); |
198 | 234 | ||
235 | /* Initialize the control handler. */ | ||
236 | v4l2_ctrl_handler_init(&rpf->ctrls, 1); | ||
237 | v4l2_ctrl_new_std(&rpf->ctrls, &rpf_ctrl_ops, V4L2_CID_ALPHA_COMPONENT, | ||
238 | 0, 255, 1, 255); | ||
239 | |||
240 | rpf->entity.subdev.ctrl_handler = &rpf->ctrls; | ||
241 | |||
242 | if (rpf->ctrls.error) { | ||
243 | dev_err(vsp1->dev, "rpf%u: failed to initialize controls\n", | ||
244 | index); | ||
245 | ret = rpf->ctrls.error; | ||
246 | goto error; | ||
247 | } | ||
248 | |||
199 | /* Initialize the video device. */ | 249 | /* Initialize the video device. */ |
200 | video = &rpf->video; | 250 | video = &rpf->video; |
201 | 251 | ||
@@ -205,7 +255,9 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index) | |||
205 | 255 | ||
206 | ret = vsp1_video_init(video, &rpf->entity); | 256 | ret = vsp1_video_init(video, &rpf->entity); |
207 | if (ret < 0) | 257 | if (ret < 0) |
208 | goto error_video; | 258 | goto error; |
259 | |||
260 | rpf->entity.video = video; | ||
209 | 261 | ||
210 | /* Connect the video device to the RPF. */ | 262 | /* Connect the video device to the RPF. */ |
211 | ret = media_entity_create_link(&rpf->video.video.entity, 0, | 263 | ret = media_entity_create_link(&rpf->video.video.entity, 0, |
@@ -214,13 +266,11 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index) | |||
214 | MEDIA_LNK_FL_ENABLED | | 266 | MEDIA_LNK_FL_ENABLED | |
215 | MEDIA_LNK_FL_IMMUTABLE); | 267 | MEDIA_LNK_FL_IMMUTABLE); |
216 | if (ret < 0) | 268 | if (ret < 0) |
217 | goto error_link; | 269 | goto error; |
218 | 270 | ||
219 | return rpf; | 271 | return rpf; |
220 | 272 | ||
221 | error_link: | 273 | error: |
222 | vsp1_video_cleanup(video); | 274 | vsp1_entity_destroy(&rpf->entity); |
223 | error_video: | ||
224 | media_entity_cleanup(&rpf->entity.subdev.entity); | ||
225 | return ERR_PTR(ret); | 275 | return ERR_PTR(ret); |
226 | } | 276 | } |
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h index b4fb65e58770..28dd9e7b3838 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.h +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h | |||
@@ -14,6 +14,7 @@ | |||
14 | #define __VSP1_RWPF_H__ | 14 | #define __VSP1_RWPF_H__ |
15 | 15 | ||
16 | #include <media/media-entity.h> | 16 | #include <media/media-entity.h> |
17 | #include <media/v4l2-ctrls.h> | ||
17 | #include <media/v4l2-subdev.h> | 18 | #include <media/v4l2-subdev.h> |
18 | 19 | ||
19 | #include "vsp1.h" | 20 | #include "vsp1.h" |
@@ -26,6 +27,7 @@ | |||
26 | struct vsp1_rwpf { | 27 | struct vsp1_rwpf { |
27 | struct vsp1_entity entity; | 28 | struct vsp1_entity entity; |
28 | struct vsp1_video video; | 29 | struct vsp1_video video; |
30 | struct v4l2_ctrl_handler ctrls; | ||
29 | 31 | ||
30 | unsigned int max_width; | 32 | unsigned int max_width; |
31 | unsigned int max_height; | 33 | unsigned int max_height; |
diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c index aa0e04c56f3f..b7d3c8b9f189 100644 --- a/drivers/media/platform/vsp1/vsp1_sru.c +++ b/drivers/media/platform/vsp1/vsp1_sru.c | |||
@@ -42,38 +42,6 @@ static inline void vsp1_sru_write(struct vsp1_sru *sru, u32 reg, u32 data) | |||
42 | 42 | ||
43 | #define V4L2_CID_VSP1_SRU_INTENSITY (V4L2_CID_USER_BASE + 1) | 43 | #define V4L2_CID_VSP1_SRU_INTENSITY (V4L2_CID_USER_BASE + 1) |
44 | 44 | ||
45 | static int sru_s_ctrl(struct v4l2_ctrl *ctrl) | ||
46 | { | ||
47 | struct vsp1_sru *sru = | ||
48 | container_of(ctrl->handler, struct vsp1_sru, ctrls); | ||
49 | |||
50 | switch (ctrl->id) { | ||
51 | case V4L2_CID_VSP1_SRU_INTENSITY: | ||
52 | sru->intensity = ctrl->val; | ||
53 | break; | ||
54 | } | ||
55 | |||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | static const struct v4l2_ctrl_ops sru_ctrl_ops = { | ||
60 | .s_ctrl = sru_s_ctrl, | ||
61 | }; | ||
62 | |||
63 | static const struct v4l2_ctrl_config sru_intensity_control = { | ||
64 | .ops = &sru_ctrl_ops, | ||
65 | .id = V4L2_CID_VSP1_SRU_INTENSITY, | ||
66 | .name = "Intensity", | ||
67 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
68 | .min = 1, | ||
69 | .max = 6, | ||
70 | .step = 1, | ||
71 | }; | ||
72 | |||
73 | /* ----------------------------------------------------------------------------- | ||
74 | * V4L2 Subdevice Core Operations | ||
75 | */ | ||
76 | |||
77 | struct vsp1_sru_param { | 45 | struct vsp1_sru_param { |
78 | u32 ctrl0; | 46 | u32 ctrl0; |
79 | u32 ctrl2; | 47 | u32 ctrl2; |
@@ -110,22 +78,66 @@ static const struct vsp1_sru_param vsp1_sru_params[] = { | |||
110 | }, | 78 | }, |
111 | }; | 79 | }; |
112 | 80 | ||
81 | static int sru_s_ctrl(struct v4l2_ctrl *ctrl) | ||
82 | { | ||
83 | struct vsp1_sru *sru = | ||
84 | container_of(ctrl->handler, struct vsp1_sru, ctrls); | ||
85 | const struct vsp1_sru_param *param; | ||
86 | u32 value; | ||
87 | |||
88 | switch (ctrl->id) { | ||
89 | case V4L2_CID_VSP1_SRU_INTENSITY: | ||
90 | param = &vsp1_sru_params[ctrl->val - 1]; | ||
91 | |||
92 | value = vsp1_sru_read(sru, VI6_SRU_CTRL0); | ||
93 | value &= ~(VI6_SRU_CTRL0_PARAM0_MASK | | ||
94 | VI6_SRU_CTRL0_PARAM1_MASK); | ||
95 | value |= param->ctrl0; | ||
96 | vsp1_sru_write(sru, VI6_SRU_CTRL0, value); | ||
97 | |||
98 | vsp1_sru_write(sru, VI6_SRU_CTRL2, param->ctrl2); | ||
99 | break; | ||
100 | } | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static const struct v4l2_ctrl_ops sru_ctrl_ops = { | ||
106 | .s_ctrl = sru_s_ctrl, | ||
107 | }; | ||
108 | |||
109 | static const struct v4l2_ctrl_config sru_intensity_control = { | ||
110 | .ops = &sru_ctrl_ops, | ||
111 | .id = V4L2_CID_VSP1_SRU_INTENSITY, | ||
112 | .name = "Intensity", | ||
113 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
114 | .min = 1, | ||
115 | .max = 6, | ||
116 | .def = 1, | ||
117 | .step = 1, | ||
118 | }; | ||
119 | |||
120 | /* ----------------------------------------------------------------------------- | ||
121 | * V4L2 Subdevice Core Operations | ||
122 | */ | ||
123 | |||
113 | static int sru_s_stream(struct v4l2_subdev *subdev, int enable) | 124 | static int sru_s_stream(struct v4l2_subdev *subdev, int enable) |
114 | { | 125 | { |
115 | struct vsp1_sru *sru = to_sru(subdev); | 126 | struct vsp1_sru *sru = to_sru(subdev); |
116 | const struct vsp1_sru_param *param; | ||
117 | struct v4l2_mbus_framefmt *input; | 127 | struct v4l2_mbus_framefmt *input; |
118 | struct v4l2_mbus_framefmt *output; | 128 | struct v4l2_mbus_framefmt *output; |
119 | bool upscale; | ||
120 | u32 ctrl0; | 129 | u32 ctrl0; |
130 | int ret; | ||
131 | |||
132 | ret = vsp1_entity_set_streaming(&sru->entity, enable); | ||
133 | if (ret < 0) | ||
134 | return ret; | ||
121 | 135 | ||
122 | if (!enable) | 136 | if (!enable) |
123 | return 0; | 137 | return 0; |
124 | 138 | ||
125 | input = &sru->entity.formats[SRU_PAD_SINK]; | 139 | input = &sru->entity.formats[SRU_PAD_SINK]; |
126 | output = &sru->entity.formats[SRU_PAD_SOURCE]; | 140 | output = &sru->entity.formats[SRU_PAD_SOURCE]; |
127 | upscale = input->width != output->width; | ||
128 | param = &vsp1_sru_params[sru->intensity]; | ||
129 | 141 | ||
130 | if (input->code == V4L2_MBUS_FMT_ARGB8888_1X32) | 142 | if (input->code == V4L2_MBUS_FMT_ARGB8888_1X32) |
131 | ctrl0 = VI6_SRU_CTRL0_PARAM2 | VI6_SRU_CTRL0_PARAM3 | 143 | ctrl0 = VI6_SRU_CTRL0_PARAM2 | VI6_SRU_CTRL0_PARAM3 |
@@ -133,10 +145,18 @@ static int sru_s_stream(struct v4l2_subdev *subdev, int enable) | |||
133 | else | 145 | else |
134 | ctrl0 = VI6_SRU_CTRL0_PARAM3; | 146 | ctrl0 = VI6_SRU_CTRL0_PARAM3; |
135 | 147 | ||
136 | vsp1_sru_write(sru, VI6_SRU_CTRL0, param->ctrl0 | ctrl0 | | 148 | if (input->width != output->width) |
137 | (upscale ? VI6_SRU_CTRL0_MODE_UPSCALE : 0)); | 149 | ctrl0 |= VI6_SRU_CTRL0_MODE_UPSCALE; |
150 | |||
151 | /* Take the control handler lock to ensure that the CTRL0 value won't be | ||
152 | * changed behind our back by a set control operation. | ||
153 | */ | ||
154 | mutex_lock(sru->ctrls.lock); | ||
155 | ctrl0 |= vsp1_sru_read(sru, VI6_SRU_CTRL0) | ||
156 | & (VI6_SRU_CTRL0_PARAM0_MASK | VI6_SRU_CTRL0_PARAM1_MASK); | ||
157 | mutex_unlock(sru->ctrls.lock); | ||
158 | |||
138 | vsp1_sru_write(sru, VI6_SRU_CTRL1, VI6_SRU_CTRL1_PARAM5); | 159 | vsp1_sru_write(sru, VI6_SRU_CTRL1, VI6_SRU_CTRL1_PARAM5); |
139 | vsp1_sru_write(sru, VI6_SRU_CTRL2, param->ctrl2); | ||
140 | 160 | ||
141 | return 0; | 161 | return 0; |
142 | } | 162 | } |
@@ -348,8 +368,15 @@ struct vsp1_sru *vsp1_sru_create(struct vsp1_device *vsp1) | |||
348 | /* Initialize the control handler. */ | 368 | /* Initialize the control handler. */ |
349 | v4l2_ctrl_handler_init(&sru->ctrls, 1); | 369 | v4l2_ctrl_handler_init(&sru->ctrls, 1); |
350 | v4l2_ctrl_new_custom(&sru->ctrls, &sru_intensity_control, NULL); | 370 | v4l2_ctrl_new_custom(&sru->ctrls, &sru_intensity_control, NULL); |
351 | v4l2_ctrl_handler_setup(&sru->ctrls); | 371 | |
352 | sru->entity.subdev.ctrl_handler = &sru->ctrls; | 372 | sru->entity.subdev.ctrl_handler = &sru->ctrls; |
353 | 373 | ||
374 | if (sru->ctrls.error) { | ||
375 | dev_err(vsp1->dev, "sru: failed to initialize controls\n"); | ||
376 | ret = sru->ctrls.error; | ||
377 | vsp1_entity_destroy(&sru->entity); | ||
378 | return ERR_PTR(ret); | ||
379 | } | ||
380 | |||
354 | return sru; | 381 | return sru; |
355 | } | 382 | } |
diff --git a/drivers/media/platform/vsp1/vsp1_sru.h b/drivers/media/platform/vsp1/vsp1_sru.h index 381870b74780..b6768bf3dc47 100644 --- a/drivers/media/platform/vsp1/vsp1_sru.h +++ b/drivers/media/platform/vsp1/vsp1_sru.h | |||
@@ -28,7 +28,6 @@ struct vsp1_sru { | |||
28 | struct vsp1_entity entity; | 28 | struct vsp1_entity entity; |
29 | 29 | ||
30 | struct v4l2_ctrl_handler ctrls; | 30 | struct v4l2_ctrl_handler ctrls; |
31 | unsigned int intensity; | ||
32 | }; | 31 | }; |
33 | 32 | ||
34 | static inline struct vsp1_sru *to_sru(struct v4l2_subdev *subdev) | 33 | static inline struct vsp1_sru *to_sru(struct v4l2_subdev *subdev) |
diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c index 0293bdbb4401..de92ef4944b3 100644 --- a/drivers/media/platform/vsp1/vsp1_uds.c +++ b/drivers/media/platform/vsp1/vsp1_uds.c | |||
@@ -45,6 +45,11 @@ static inline void vsp1_uds_write(struct vsp1_uds *uds, u32 reg, u32 data) | |||
45 | * Scaling Computation | 45 | * Scaling Computation |
46 | */ | 46 | */ |
47 | 47 | ||
48 | void vsp1_uds_set_alpha(struct vsp1_uds *uds, unsigned int alpha) | ||
49 | { | ||
50 | vsp1_uds_write(uds, VI6_UDS_ALPVAL, alpha << VI6_UDS_ALPVAL_VAL0_SHIFT); | ||
51 | } | ||
52 | |||
48 | /* | 53 | /* |
49 | * uds_output_size - Return the output size for an input size and scaling ratio | 54 | * uds_output_size - Return the output size for an input size and scaling ratio |
50 | * @input: input size in pixels | 55 | * @input: input size in pixels |
@@ -105,49 +110,56 @@ static unsigned int uds_compute_ratio(unsigned int input, unsigned int output) | |||
105 | return (input - 1) * 4096 / (output - 1); | 110 | return (input - 1) * 4096 / (output - 1); |
106 | } | 111 | } |
107 | 112 | ||
108 | static void uds_compute_ratios(struct vsp1_uds *uds) | ||
109 | { | ||
110 | struct v4l2_mbus_framefmt *input = &uds->entity.formats[UDS_PAD_SINK]; | ||
111 | struct v4l2_mbus_framefmt *output = | ||
112 | &uds->entity.formats[UDS_PAD_SOURCE]; | ||
113 | |||
114 | uds->hscale = uds_compute_ratio(input->width, output->width); | ||
115 | uds->vscale = uds_compute_ratio(input->height, output->height); | ||
116 | |||
117 | dev_dbg(uds->entity.vsp1->dev, "hscale %u vscale %u\n", | ||
118 | uds->hscale, uds->vscale); | ||
119 | } | ||
120 | |||
121 | /* ----------------------------------------------------------------------------- | 113 | /* ----------------------------------------------------------------------------- |
122 | * V4L2 Subdevice Core Operations | 114 | * V4L2 Subdevice Core Operations |
123 | */ | 115 | */ |
124 | 116 | ||
125 | static int uds_s_stream(struct v4l2_subdev *subdev, int enable) | 117 | static int uds_s_stream(struct v4l2_subdev *subdev, int enable) |
126 | { | 118 | { |
127 | const struct v4l2_mbus_framefmt *format; | ||
128 | struct vsp1_uds *uds = to_uds(subdev); | 119 | struct vsp1_uds *uds = to_uds(subdev); |
120 | const struct v4l2_mbus_framefmt *output; | ||
121 | const struct v4l2_mbus_framefmt *input; | ||
122 | unsigned int hscale; | ||
123 | unsigned int vscale; | ||
124 | bool multitap; | ||
129 | 125 | ||
130 | if (!enable) | 126 | if (!enable) |
131 | return 0; | 127 | return 0; |
132 | 128 | ||
133 | /* Enable multi-tap scaling. */ | 129 | input = &uds->entity.formats[UDS_PAD_SINK]; |
134 | vsp1_uds_write(uds, VI6_UDS_CTRL, VI6_UDS_CTRL_AON | VI6_UDS_CTRL_BC); | 130 | output = &uds->entity.formats[UDS_PAD_SOURCE]; |
131 | |||
132 | hscale = uds_compute_ratio(input->width, output->width); | ||
133 | vscale = uds_compute_ratio(input->height, output->height); | ||
134 | |||
135 | dev_dbg(uds->entity.vsp1->dev, "hscale %u vscale %u\n", hscale, vscale); | ||
136 | |||
137 | /* Multi-tap scaling can't be enabled along with alpha scaling when | ||
138 | * scaling down with a factor lower than or equal to 1/2 in either | ||
139 | * direction. | ||
140 | */ | ||
141 | if (uds->scale_alpha && (hscale >= 8192 || vscale >= 8192)) | ||
142 | multitap = false; | ||
143 | else | ||
144 | multitap = true; | ||
145 | |||
146 | vsp1_uds_write(uds, VI6_UDS_CTRL, | ||
147 | (uds->scale_alpha ? VI6_UDS_CTRL_AON : 0) | | ||
148 | (multitap ? VI6_UDS_CTRL_BC : 0)); | ||
135 | 149 | ||
136 | vsp1_uds_write(uds, VI6_UDS_PASS_BWIDTH, | 150 | vsp1_uds_write(uds, VI6_UDS_PASS_BWIDTH, |
137 | (uds_passband_width(uds->hscale) | 151 | (uds_passband_width(hscale) |
138 | << VI6_UDS_PASS_BWIDTH_H_SHIFT) | | 152 | << VI6_UDS_PASS_BWIDTH_H_SHIFT) | |
139 | (uds_passband_width(uds->vscale) | 153 | (uds_passband_width(vscale) |
140 | << VI6_UDS_PASS_BWIDTH_V_SHIFT)); | 154 | << VI6_UDS_PASS_BWIDTH_V_SHIFT)); |
141 | 155 | ||
142 | /* Set the scaling ratios and the output size. */ | 156 | /* Set the scaling ratios and the output size. */ |
143 | format = &uds->entity.formats[UDS_PAD_SOURCE]; | ||
144 | |||
145 | vsp1_uds_write(uds, VI6_UDS_SCALE, | 157 | vsp1_uds_write(uds, VI6_UDS_SCALE, |
146 | (uds->hscale << VI6_UDS_SCALE_HFRAC_SHIFT) | | 158 | (hscale << VI6_UDS_SCALE_HFRAC_SHIFT) | |
147 | (uds->vscale << VI6_UDS_SCALE_VFRAC_SHIFT)); | 159 | (vscale << VI6_UDS_SCALE_VFRAC_SHIFT)); |
148 | vsp1_uds_write(uds, VI6_UDS_CLIP_SIZE, | 160 | vsp1_uds_write(uds, VI6_UDS_CLIP_SIZE, |
149 | (format->width << VI6_UDS_CLIP_SIZE_HSIZE_SHIFT) | | 161 | (output->width << VI6_UDS_CLIP_SIZE_HSIZE_SHIFT) | |
150 | (format->height << VI6_UDS_CLIP_SIZE_VSIZE_SHIFT)); | 162 | (output->height << VI6_UDS_CLIP_SIZE_VSIZE_SHIFT)); |
151 | 163 | ||
152 | return 0; | 164 | return 0; |
153 | } | 165 | } |
@@ -280,9 +292,6 @@ static int uds_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, | |||
280 | uds_try_format(uds, fh, UDS_PAD_SOURCE, format, fmt->which); | 292 | uds_try_format(uds, fh, UDS_PAD_SOURCE, format, fmt->which); |
281 | } | 293 | } |
282 | 294 | ||
283 | if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) | ||
284 | uds_compute_ratios(uds); | ||
285 | |||
286 | return 0; | 295 | return 0; |
287 | } | 296 | } |
288 | 297 | ||
diff --git a/drivers/media/platform/vsp1/vsp1_uds.h b/drivers/media/platform/vsp1/vsp1_uds.h index 479d12df1180..031ac0da1b66 100644 --- a/drivers/media/platform/vsp1/vsp1_uds.h +++ b/drivers/media/platform/vsp1/vsp1_uds.h | |||
@@ -25,9 +25,7 @@ struct vsp1_device; | |||
25 | 25 | ||
26 | struct vsp1_uds { | 26 | struct vsp1_uds { |
27 | struct vsp1_entity entity; | 27 | struct vsp1_entity entity; |
28 | 28 | bool scale_alpha; | |
29 | unsigned int hscale; | ||
30 | unsigned int vscale; | ||
31 | }; | 29 | }; |
32 | 30 | ||
33 | static inline struct vsp1_uds *to_uds(struct v4l2_subdev *subdev) | 31 | static inline struct vsp1_uds *to_uds(struct v4l2_subdev *subdev) |
@@ -37,4 +35,6 @@ static inline struct vsp1_uds *to_uds(struct v4l2_subdev *subdev) | |||
37 | 35 | ||
38 | struct vsp1_uds *vsp1_uds_create(struct vsp1_device *vsp1, unsigned int index); | 36 | struct vsp1_uds *vsp1_uds_create(struct vsp1_device *vsp1, unsigned int index); |
39 | 37 | ||
38 | void vsp1_uds_set_alpha(struct vsp1_uds *uds, unsigned int alpha); | ||
39 | |||
40 | #endif /* __VSP1_UDS_H__ */ | 40 | #endif /* __VSP1_UDS_H__ */ |
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 8a1253e51f04..915a20eb003e 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include "vsp1_bru.h" | 31 | #include "vsp1_bru.h" |
32 | #include "vsp1_entity.h" | 32 | #include "vsp1_entity.h" |
33 | #include "vsp1_rwpf.h" | 33 | #include "vsp1_rwpf.h" |
34 | #include "vsp1_uds.h" | ||
34 | #include "vsp1_video.h" | 35 | #include "vsp1_video.h" |
35 | 36 | ||
36 | #define VSP1_VIDEO_DEF_FORMAT V4L2_PIX_FMT_YUYV | 37 | #define VSP1_VIDEO_DEF_FORMAT V4L2_PIX_FMT_YUYV |
@@ -50,70 +51,85 @@ static const struct vsp1_format_info vsp1_video_formats[] = { | |||
50 | { V4L2_PIX_FMT_RGB332, V4L2_MBUS_FMT_ARGB8888_1X32, | 51 | { V4L2_PIX_FMT_RGB332, V4L2_MBUS_FMT_ARGB8888_1X32, |
51 | VI6_FMT_RGB_332, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | 52 | VI6_FMT_RGB_332, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | |
52 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | 53 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, |
53 | 1, { 8, 0, 0 }, false, false, 1, 1 }, | 54 | 1, { 8, 0, 0 }, false, false, 1, 1, false }, |
54 | { V4L2_PIX_FMT_RGB444, V4L2_MBUS_FMT_ARGB8888_1X32, | 55 | { V4L2_PIX_FMT_ARGB444, V4L2_MBUS_FMT_ARGB8888_1X32, |
56 | VI6_FMT_ARGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
57 | VI6_RPF_DSWAP_P_WDS, | ||
58 | 1, { 16, 0, 0 }, false, false, 1, 1, true }, | ||
59 | { V4L2_PIX_FMT_XRGB444, V4L2_MBUS_FMT_ARGB8888_1X32, | ||
55 | VI6_FMT_XRGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | 60 | VI6_FMT_XRGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | |
56 | VI6_RPF_DSWAP_P_WDS, | 61 | VI6_RPF_DSWAP_P_WDS, |
57 | 1, { 16, 0, 0 }, false, false, 1, 1 }, | 62 | 1, { 16, 0, 0 }, false, false, 1, 1, true }, |
58 | { V4L2_PIX_FMT_RGB555, V4L2_MBUS_FMT_ARGB8888_1X32, | 63 | { V4L2_PIX_FMT_ARGB555, V4L2_MBUS_FMT_ARGB8888_1X32, |
64 | VI6_FMT_ARGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
65 | VI6_RPF_DSWAP_P_WDS, | ||
66 | 1, { 16, 0, 0 }, false, false, 1, 1, true }, | ||
67 | { V4L2_PIX_FMT_XRGB555, V4L2_MBUS_FMT_ARGB8888_1X32, | ||
59 | VI6_FMT_XRGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | 68 | VI6_FMT_XRGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | |
60 | VI6_RPF_DSWAP_P_WDS, | 69 | VI6_RPF_DSWAP_P_WDS, |
61 | 1, { 16, 0, 0 }, false, false, 1, 1 }, | 70 | 1, { 16, 0, 0 }, false, false, 1, 1, false }, |
62 | { V4L2_PIX_FMT_RGB565, V4L2_MBUS_FMT_ARGB8888_1X32, | 71 | { V4L2_PIX_FMT_RGB565, V4L2_MBUS_FMT_ARGB8888_1X32, |
63 | VI6_FMT_RGB_565, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | 72 | VI6_FMT_RGB_565, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | |
64 | VI6_RPF_DSWAP_P_WDS, | 73 | VI6_RPF_DSWAP_P_WDS, |
65 | 1, { 16, 0, 0 }, false, false, 1, 1 }, | 74 | 1, { 16, 0, 0 }, false, false, 1, 1, false }, |
66 | { V4L2_PIX_FMT_BGR24, V4L2_MBUS_FMT_ARGB8888_1X32, | 75 | { V4L2_PIX_FMT_BGR24, V4L2_MBUS_FMT_ARGB8888_1X32, |
67 | VI6_FMT_BGR_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | 76 | VI6_FMT_BGR_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | |
68 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | 77 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, |
69 | 1, { 24, 0, 0 }, false, false, 1, 1 }, | 78 | 1, { 24, 0, 0 }, false, false, 1, 1, false }, |
70 | { V4L2_PIX_FMT_RGB24, V4L2_MBUS_FMT_ARGB8888_1X32, | 79 | { V4L2_PIX_FMT_RGB24, V4L2_MBUS_FMT_ARGB8888_1X32, |
71 | VI6_FMT_RGB_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | 80 | VI6_FMT_RGB_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | |
72 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | 81 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, |
73 | 1, { 24, 0, 0 }, false, false, 1, 1 }, | 82 | 1, { 24, 0, 0 }, false, false, 1, 1, false }, |
74 | { V4L2_PIX_FMT_BGR32, V4L2_MBUS_FMT_ARGB8888_1X32, | 83 | { V4L2_PIX_FMT_ABGR32, V4L2_MBUS_FMT_ARGB8888_1X32, |
84 | VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS, | ||
85 | 1, { 32, 0, 0 }, false, false, 1, 1, true }, | ||
86 | { V4L2_PIX_FMT_XBGR32, V4L2_MBUS_FMT_ARGB8888_1X32, | ||
75 | VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS, | 87 | VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS, |
76 | 1, { 32, 0, 0 }, false, false, 1, 1 }, | 88 | 1, { 32, 0, 0 }, false, false, 1, 1, false }, |
77 | { V4L2_PIX_FMT_RGB32, V4L2_MBUS_FMT_ARGB8888_1X32, | 89 | { V4L2_PIX_FMT_ARGB32, V4L2_MBUS_FMT_ARGB8888_1X32, |
90 | VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
91 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | ||
92 | 1, { 32, 0, 0 }, false, false, 1, 1, true }, | ||
93 | { V4L2_PIX_FMT_XRGB32, V4L2_MBUS_FMT_ARGB8888_1X32, | ||
78 | VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | 94 | VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | |
79 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | 95 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, |
80 | 1, { 32, 0, 0 }, false, false, 1, 1 }, | 96 | 1, { 32, 0, 0 }, false, false, 1, 1, false }, |
81 | { V4L2_PIX_FMT_UYVY, V4L2_MBUS_FMT_AYUV8_1X32, | 97 | { V4L2_PIX_FMT_UYVY, V4L2_MBUS_FMT_AYUV8_1X32, |
82 | VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | 98 | VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | |
83 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | 99 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, |
84 | 1, { 16, 0, 0 }, false, false, 2, 1 }, | 100 | 1, { 16, 0, 0 }, false, false, 2, 1, false }, |
85 | { V4L2_PIX_FMT_VYUY, V4L2_MBUS_FMT_AYUV8_1X32, | 101 | { V4L2_PIX_FMT_VYUY, V4L2_MBUS_FMT_AYUV8_1X32, |
86 | VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | 102 | VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | |
87 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | 103 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, |
88 | 1, { 16, 0, 0 }, false, true, 2, 1 }, | 104 | 1, { 16, 0, 0 }, false, true, 2, 1, false }, |
89 | { V4L2_PIX_FMT_YUYV, V4L2_MBUS_FMT_AYUV8_1X32, | 105 | { V4L2_PIX_FMT_YUYV, V4L2_MBUS_FMT_AYUV8_1X32, |
90 | VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | 106 | VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | |
91 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | 107 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, |
92 | 1, { 16, 0, 0 }, true, false, 2, 1 }, | 108 | 1, { 16, 0, 0 }, true, false, 2, 1, false }, |
93 | { V4L2_PIX_FMT_YVYU, V4L2_MBUS_FMT_AYUV8_1X32, | 109 | { V4L2_PIX_FMT_YVYU, V4L2_MBUS_FMT_AYUV8_1X32, |
94 | VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | 110 | VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | |
95 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | 111 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, |
96 | 1, { 16, 0, 0 }, true, true, 2, 1 }, | 112 | 1, { 16, 0, 0 }, true, true, 2, 1, false }, |
97 | { V4L2_PIX_FMT_NV12M, V4L2_MBUS_FMT_AYUV8_1X32, | 113 | { V4L2_PIX_FMT_NV12M, V4L2_MBUS_FMT_AYUV8_1X32, |
98 | VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | 114 | VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | |
99 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | 115 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, |
100 | 2, { 8, 16, 0 }, false, false, 2, 2 }, | 116 | 2, { 8, 16, 0 }, false, false, 2, 2, false }, |
101 | { V4L2_PIX_FMT_NV21M, V4L2_MBUS_FMT_AYUV8_1X32, | 117 | { V4L2_PIX_FMT_NV21M, V4L2_MBUS_FMT_AYUV8_1X32, |
102 | VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | 118 | VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | |
103 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | 119 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, |
104 | 2, { 8, 16, 0 }, false, true, 2, 2 }, | 120 | 2, { 8, 16, 0 }, false, true, 2, 2, false }, |
105 | { V4L2_PIX_FMT_NV16M, V4L2_MBUS_FMT_AYUV8_1X32, | 121 | { V4L2_PIX_FMT_NV16M, V4L2_MBUS_FMT_AYUV8_1X32, |
106 | VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | 122 | VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | |
107 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | 123 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, |
108 | 2, { 8, 16, 0 }, false, false, 2, 1 }, | 124 | 2, { 8, 16, 0 }, false, false, 2, 1, false }, |
109 | { V4L2_PIX_FMT_NV61M, V4L2_MBUS_FMT_AYUV8_1X32, | 125 | { V4L2_PIX_FMT_NV61M, V4L2_MBUS_FMT_AYUV8_1X32, |
110 | VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | 126 | VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | |
111 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | 127 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, |
112 | 2, { 8, 16, 0 }, false, true, 2, 1 }, | 128 | 2, { 8, 16, 0 }, false, true, 2, 1, false }, |
113 | { V4L2_PIX_FMT_YUV420M, V4L2_MBUS_FMT_AYUV8_1X32, | 129 | { V4L2_PIX_FMT_YUV420M, V4L2_MBUS_FMT_AYUV8_1X32, |
114 | VI6_FMT_Y_U_V_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | 130 | VI6_FMT_Y_U_V_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | |
115 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | 131 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, |
116 | 3, { 8, 8, 8 }, false, false, 2, 2 }, | 132 | 3, { 8, 8, 8 }, false, false, 2, 2, false }, |
117 | }; | 133 | }; |
118 | 134 | ||
119 | /* | 135 | /* |
@@ -181,11 +197,29 @@ static int __vsp1_video_try_format(struct vsp1_video *video, | |||
181 | struct v4l2_pix_format_mplane *pix, | 197 | struct v4l2_pix_format_mplane *pix, |
182 | const struct vsp1_format_info **fmtinfo) | 198 | const struct vsp1_format_info **fmtinfo) |
183 | { | 199 | { |
200 | static const u32 xrgb_formats[][2] = { | ||
201 | { V4L2_PIX_FMT_RGB444, V4L2_PIX_FMT_XRGB444 }, | ||
202 | { V4L2_PIX_FMT_RGB555, V4L2_PIX_FMT_XRGB555 }, | ||
203 | { V4L2_PIX_FMT_BGR32, V4L2_PIX_FMT_XBGR32 }, | ||
204 | { V4L2_PIX_FMT_RGB32, V4L2_PIX_FMT_XRGB32 }, | ||
205 | }; | ||
206 | |||
184 | const struct vsp1_format_info *info; | 207 | const struct vsp1_format_info *info; |
185 | unsigned int width = pix->width; | 208 | unsigned int width = pix->width; |
186 | unsigned int height = pix->height; | 209 | unsigned int height = pix->height; |
187 | unsigned int i; | 210 | unsigned int i; |
188 | 211 | ||
212 | /* Backward compatibility: replace deprecated RGB formats by their XRGB | ||
213 | * equivalent. This selects the format older userspace applications want | ||
214 | * while still exposing the new format. | ||
215 | */ | ||
216 | for (i = 0; i < ARRAY_SIZE(xrgb_formats); ++i) { | ||
217 | if (xrgb_formats[i][0] == pix->pixelformat) { | ||
218 | pix->pixelformat = xrgb_formats[i][1]; | ||
219 | break; | ||
220 | } | ||
221 | } | ||
222 | |||
189 | /* Retrieve format information and select the default format if the | 223 | /* Retrieve format information and select the default format if the |
190 | * requested format isn't supported. | 224 | * requested format isn't supported. |
191 | */ | 225 | */ |
@@ -273,13 +307,14 @@ vsp1_video_format_adjust(struct vsp1_video *video, | |||
273 | * Pipeline Management | 307 | * Pipeline Management |
274 | */ | 308 | */ |
275 | 309 | ||
276 | static int vsp1_pipeline_validate_branch(struct vsp1_rwpf *input, | 310 | static int vsp1_pipeline_validate_branch(struct vsp1_pipeline *pipe, |
311 | struct vsp1_rwpf *input, | ||
277 | struct vsp1_rwpf *output) | 312 | struct vsp1_rwpf *output) |
278 | { | 313 | { |
279 | struct vsp1_entity *entity; | 314 | struct vsp1_entity *entity; |
280 | unsigned int entities = 0; | 315 | unsigned int entities = 0; |
281 | struct media_pad *pad; | 316 | struct media_pad *pad; |
282 | bool uds_found = false; | 317 | bool bru_found = false; |
283 | 318 | ||
284 | input->location.left = 0; | 319 | input->location.left = 0; |
285 | input->location.top = 0; | 320 | input->location.top = 0; |
@@ -301,10 +336,15 @@ static int vsp1_pipeline_validate_branch(struct vsp1_rwpf *input, | |||
301 | */ | 336 | */ |
302 | if (entity->type == VSP1_ENTITY_BRU) { | 337 | if (entity->type == VSP1_ENTITY_BRU) { |
303 | struct vsp1_bru *bru = to_bru(&entity->subdev); | 338 | struct vsp1_bru *bru = to_bru(&entity->subdev); |
304 | struct v4l2_rect *rect = &bru->compose[pad->index]; | 339 | struct v4l2_rect *rect = |
340 | &bru->inputs[pad->index].compose; | ||
341 | |||
342 | bru->inputs[pad->index].rpf = input; | ||
305 | 343 | ||
306 | input->location.left = rect->left; | 344 | input->location.left = rect->left; |
307 | input->location.top = rect->top; | 345 | input->location.top = rect->top; |
346 | |||
347 | bru_found = true; | ||
308 | } | 348 | } |
309 | 349 | ||
310 | /* We've reached the WPF, we're done. */ | 350 | /* We've reached the WPF, we're done. */ |
@@ -319,9 +359,12 @@ static int vsp1_pipeline_validate_branch(struct vsp1_rwpf *input, | |||
319 | 359 | ||
320 | /* UDS can't be chained. */ | 360 | /* UDS can't be chained. */ |
321 | if (entity->type == VSP1_ENTITY_UDS) { | 361 | if (entity->type == VSP1_ENTITY_UDS) { |
322 | if (uds_found) | 362 | if (pipe->uds) |
323 | return -EPIPE; | 363 | return -EPIPE; |
324 | uds_found = true; | 364 | |
365 | pipe->uds = entity; | ||
366 | pipe->uds_input = bru_found ? pipe->bru | ||
367 | : &input->entity; | ||
325 | } | 368 | } |
326 | 369 | ||
327 | /* Follow the source link. The link setup operations ensure | 370 | /* Follow the source link. The link setup operations ensure |
@@ -340,6 +383,27 @@ static int vsp1_pipeline_validate_branch(struct vsp1_rwpf *input, | |||
340 | return 0; | 383 | return 0; |
341 | } | 384 | } |
342 | 385 | ||
386 | static void __vsp1_pipeline_cleanup(struct vsp1_pipeline *pipe) | ||
387 | { | ||
388 | if (pipe->bru) { | ||
389 | struct vsp1_bru *bru = to_bru(&pipe->bru->subdev); | ||
390 | unsigned int i; | ||
391 | |||
392 | for (i = 0; i < ARRAY_SIZE(bru->inputs); ++i) | ||
393 | bru->inputs[i].rpf = NULL; | ||
394 | } | ||
395 | |||
396 | INIT_LIST_HEAD(&pipe->entities); | ||
397 | pipe->state = VSP1_PIPELINE_STOPPED; | ||
398 | pipe->buffers_ready = 0; | ||
399 | pipe->num_video = 0; | ||
400 | pipe->num_inputs = 0; | ||
401 | pipe->output = NULL; | ||
402 | pipe->bru = NULL; | ||
403 | pipe->lif = NULL; | ||
404 | pipe->uds = NULL; | ||
405 | } | ||
406 | |||
343 | static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe, | 407 | static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe, |
344 | struct vsp1_video *video) | 408 | struct vsp1_video *video) |
345 | { | 409 | { |
@@ -395,7 +459,7 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe, | |||
395 | * contains no loop and that all branches end at the output WPF. | 459 | * contains no loop and that all branches end at the output WPF. |
396 | */ | 460 | */ |
397 | for (i = 0; i < pipe->num_inputs; ++i) { | 461 | for (i = 0; i < pipe->num_inputs; ++i) { |
398 | ret = vsp1_pipeline_validate_branch(pipe->inputs[i], | 462 | ret = vsp1_pipeline_validate_branch(pipe, pipe->inputs[i], |
399 | pipe->output); | 463 | pipe->output); |
400 | if (ret < 0) | 464 | if (ret < 0) |
401 | goto error; | 465 | goto error; |
@@ -404,13 +468,7 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe, | |||
404 | return 0; | 468 | return 0; |
405 | 469 | ||
406 | error: | 470 | error: |
407 | INIT_LIST_HEAD(&pipe->entities); | 471 | __vsp1_pipeline_cleanup(pipe); |
408 | pipe->buffers_ready = 0; | ||
409 | pipe->num_video = 0; | ||
410 | pipe->num_inputs = 0; | ||
411 | pipe->output = NULL; | ||
412 | pipe->bru = NULL; | ||
413 | pipe->lif = NULL; | ||
414 | return ret; | 472 | return ret; |
415 | } | 473 | } |
416 | 474 | ||
@@ -441,16 +499,8 @@ static void vsp1_pipeline_cleanup(struct vsp1_pipeline *pipe) | |||
441 | mutex_lock(&pipe->lock); | 499 | mutex_lock(&pipe->lock); |
442 | 500 | ||
443 | /* If we're the last user clean up the pipeline. */ | 501 | /* If we're the last user clean up the pipeline. */ |
444 | if (--pipe->use_count == 0) { | 502 | if (--pipe->use_count == 0) |
445 | INIT_LIST_HEAD(&pipe->entities); | 503 | __vsp1_pipeline_cleanup(pipe); |
446 | pipe->state = VSP1_PIPELINE_STOPPED; | ||
447 | pipe->buffers_ready = 0; | ||
448 | pipe->num_video = 0; | ||
449 | pipe->num_inputs = 0; | ||
450 | pipe->output = NULL; | ||
451 | pipe->bru = NULL; | ||
452 | pipe->lif = NULL; | ||
453 | } | ||
454 | 504 | ||
455 | mutex_unlock(&pipe->lock); | 505 | mutex_unlock(&pipe->lock); |
456 | } | 506 | } |
@@ -471,7 +521,8 @@ static int vsp1_pipeline_stop(struct vsp1_pipeline *pipe) | |||
471 | int ret; | 521 | int ret; |
472 | 522 | ||
473 | spin_lock_irqsave(&pipe->irqlock, flags); | 523 | spin_lock_irqsave(&pipe->irqlock, flags); |
474 | pipe->state = VSP1_PIPELINE_STOPPING; | 524 | if (pipe->state == VSP1_PIPELINE_RUNNING) |
525 | pipe->state = VSP1_PIPELINE_STOPPING; | ||
475 | spin_unlock_irqrestore(&pipe->irqlock, flags); | 526 | spin_unlock_irqrestore(&pipe->irqlock, flags); |
476 | 527 | ||
477 | ret = wait_event_timeout(pipe->wq, pipe->state == VSP1_PIPELINE_STOPPED, | 528 | ret = wait_event_timeout(pipe->wq, pipe->state == VSP1_PIPELINE_STOPPED, |
@@ -479,7 +530,7 @@ static int vsp1_pipeline_stop(struct vsp1_pipeline *pipe) | |||
479 | ret = ret == 0 ? -ETIMEDOUT : 0; | 530 | ret = ret == 0 ? -ETIMEDOUT : 0; |
480 | 531 | ||
481 | list_for_each_entry(entity, &pipe->entities, list_pipe) { | 532 | list_for_each_entry(entity, &pipe->entities, list_pipe) { |
482 | if (entity->route) | 533 | if (entity->route && entity->route->reg) |
483 | vsp1_write(entity->vsp1, entity->route->reg, | 534 | vsp1_write(entity->vsp1, entity->route->reg, |
484 | VI6_DPR_NODE_UNUSED); | 535 | VI6_DPR_NODE_UNUSED); |
485 | 536 | ||
@@ -576,6 +627,7 @@ static void vsp1_video_frame_end(struct vsp1_pipeline *pipe, | |||
576 | 627 | ||
577 | void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe) | 628 | void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe) |
578 | { | 629 | { |
630 | enum vsp1_pipeline_state state; | ||
579 | unsigned long flags; | 631 | unsigned long flags; |
580 | unsigned int i; | 632 | unsigned int i; |
581 | 633 | ||
@@ -591,11 +643,13 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe) | |||
591 | 643 | ||
592 | spin_lock_irqsave(&pipe->irqlock, flags); | 644 | spin_lock_irqsave(&pipe->irqlock, flags); |
593 | 645 | ||
646 | state = pipe->state; | ||
647 | pipe->state = VSP1_PIPELINE_STOPPED; | ||
648 | |||
594 | /* If a stop has been requested, mark the pipeline as stopped and | 649 | /* If a stop has been requested, mark the pipeline as stopped and |
595 | * return. | 650 | * return. |
596 | */ | 651 | */ |
597 | if (pipe->state == VSP1_PIPELINE_STOPPING) { | 652 | if (state == VSP1_PIPELINE_STOPPING) { |
598 | pipe->state = VSP1_PIPELINE_STOPPED; | ||
599 | wake_up(&pipe->wq); | 653 | wake_up(&pipe->wq); |
600 | goto done; | 654 | goto done; |
601 | } | 655 | } |
@@ -608,6 +662,47 @@ done: | |||
608 | spin_unlock_irqrestore(&pipe->irqlock, flags); | 662 | spin_unlock_irqrestore(&pipe->irqlock, flags); |
609 | } | 663 | } |
610 | 664 | ||
665 | /* | ||
666 | * Propagate the alpha value through the pipeline. | ||
667 | * | ||
668 | * As the UDS has restricted scaling capabilities when the alpha component needs | ||
669 | * to be scaled, we disable alpha scaling when the UDS input has a fixed alpha | ||
670 | * value. The UDS then outputs a fixed alpha value which needs to be programmed | ||
671 | * from the input RPF alpha. | ||
672 | */ | ||
673 | void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe, | ||
674 | struct vsp1_entity *input, | ||
675 | unsigned int alpha) | ||
676 | { | ||
677 | struct vsp1_entity *entity; | ||
678 | struct media_pad *pad; | ||
679 | |||
680 | pad = media_entity_remote_pad(&input->pads[RWPF_PAD_SOURCE]); | ||
681 | |||
682 | while (pad) { | ||
683 | if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) | ||
684 | break; | ||
685 | |||
686 | entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity)); | ||
687 | |||
688 | /* The BRU background color has a fixed alpha value set to 255, | ||
689 | * the output alpha value is thus always equal to 255. | ||
690 | */ | ||
691 | if (entity->type == VSP1_ENTITY_BRU) | ||
692 | alpha = 255; | ||
693 | |||
694 | if (entity->type == VSP1_ENTITY_UDS) { | ||
695 | struct vsp1_uds *uds = to_uds(&entity->subdev); | ||
696 | |||
697 | vsp1_uds_set_alpha(uds, alpha); | ||
698 | break; | ||
699 | } | ||
700 | |||
701 | pad = &entity->pads[entity->source_pad]; | ||
702 | pad = media_entity_remote_pad(pad); | ||
703 | } | ||
704 | } | ||
705 | |||
611 | /* ----------------------------------------------------------------------------- | 706 | /* ----------------------------------------------------------------------------- |
612 | * videobuf2 Queue Operations | 707 | * videobuf2 Queue Operations |
613 | */ | 708 | */ |
@@ -654,8 +749,6 @@ static int vsp1_video_buffer_prepare(struct vb2_buffer *vb) | |||
654 | if (vb->num_planes < format->num_planes) | 749 | if (vb->num_planes < format->num_planes) |
655 | return -EINVAL; | 750 | return -EINVAL; |
656 | 751 | ||
657 | buf->video = video; | ||
658 | |||
659 | for (i = 0; i < vb->num_planes; ++i) { | 752 | for (i = 0; i < vb->num_planes; ++i) { |
660 | buf->addr[i] = vb2_dma_contig_plane_dma_addr(vb, i); | 753 | buf->addr[i] = vb2_dma_contig_plane_dma_addr(vb, i); |
661 | buf->length[i] = vb2_plane_size(vb, i); | 754 | buf->length[i] = vb2_plane_size(vb, i); |
@@ -717,6 +810,25 @@ static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count) | |||
717 | 810 | ||
718 | mutex_lock(&pipe->lock); | 811 | mutex_lock(&pipe->lock); |
719 | if (pipe->stream_count == pipe->num_video - 1) { | 812 | if (pipe->stream_count == pipe->num_video - 1) { |
813 | if (pipe->uds) { | ||
814 | struct vsp1_uds *uds = to_uds(&pipe->uds->subdev); | ||
815 | |||
816 | /* If a BRU is present in the pipeline before the UDS, | ||
817 | * the alpha component doesn't need to be scaled as the | ||
818 | * BRU output alpha value is fixed to 255. Otherwise we | ||
819 | * need to scale the alpha component only when available | ||
820 | * at the input RPF. | ||
821 | */ | ||
822 | if (pipe->uds_input->type == VSP1_ENTITY_BRU) { | ||
823 | uds->scale_alpha = false; | ||
824 | } else { | ||
825 | struct vsp1_rwpf *rpf = | ||
826 | to_rwpf(&pipe->uds_input->subdev); | ||
827 | |||
828 | uds->scale_alpha = rpf->video.fmtinfo->alpha; | ||
829 | } | ||
830 | } | ||
831 | |||
720 | list_for_each_entry(entity, &pipe->entities, list_pipe) { | 832 | list_for_each_entry(entity, &pipe->entities, list_pipe) { |
721 | vsp1_entity_route_setup(entity); | 833 | vsp1_entity_route_setup(entity); |
722 | 834 | ||
@@ -744,6 +856,7 @@ static void vsp1_video_stop_streaming(struct vb2_queue *vq) | |||
744 | { | 856 | { |
745 | struct vsp1_video *video = vb2_get_drv_priv(vq); | 857 | struct vsp1_video *video = vb2_get_drv_priv(vq); |
746 | struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity); | 858 | struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity); |
859 | struct vsp1_video_buffer *buffer; | ||
747 | unsigned long flags; | 860 | unsigned long flags; |
748 | int ret; | 861 | int ret; |
749 | 862 | ||
@@ -761,6 +874,8 @@ static void vsp1_video_stop_streaming(struct vb2_queue *vq) | |||
761 | 874 | ||
762 | /* Remove all buffers from the IRQ queue. */ | 875 | /* Remove all buffers from the IRQ queue. */ |
763 | spin_lock_irqsave(&video->irqlock, flags); | 876 | spin_lock_irqsave(&video->irqlock, flags); |
877 | list_for_each_entry(buffer, &video->irqqueue, queue) | ||
878 | vb2_buffer_done(&buffer->buf, VB2_BUF_STATE_ERROR); | ||
764 | INIT_LIST_HEAD(&video->irqqueue); | 879 | INIT_LIST_HEAD(&video->irqqueue); |
765 | spin_unlock_irqrestore(&video->irqlock, flags); | 880 | spin_unlock_irqrestore(&video->irqlock, flags); |
766 | } | 881 | } |
@@ -950,8 +1065,8 @@ static int vsp1_video_open(struct file *file) | |||
950 | 1065 | ||
951 | file->private_data = vfh; | 1066 | file->private_data = vfh; |
952 | 1067 | ||
953 | if (!vsp1_device_get(video->vsp1)) { | 1068 | ret = vsp1_device_get(video->vsp1); |
954 | ret = -EBUSY; | 1069 | if (ret < 0) { |
955 | v4l2_fh_del(vfh); | 1070 | v4l2_fh_del(vfh); |
956 | kfree(vfh); | 1071 | kfree(vfh); |
957 | } | 1072 | } |
diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h index c04d48fa2999..fd2851a82e00 100644 --- a/drivers/media/platform/vsp1/vsp1_video.h +++ b/drivers/media/platform/vsp1/vsp1_video.h | |||
@@ -33,6 +33,7 @@ struct vsp1_video; | |||
33 | * @swap_uv: the U and V components are swapped (V comes before U) | 33 | * @swap_uv: the U and V components are swapped (V comes before U) |
34 | * @hsub: horizontal subsampling factor | 34 | * @hsub: horizontal subsampling factor |
35 | * @vsub: vertical subsampling factor | 35 | * @vsub: vertical subsampling factor |
36 | * @alpha: has an alpha channel | ||
36 | */ | 37 | */ |
37 | struct vsp1_format_info { | 38 | struct vsp1_format_info { |
38 | u32 fourcc; | 39 | u32 fourcc; |
@@ -45,6 +46,7 @@ struct vsp1_format_info { | |||
45 | bool swap_uv; | 46 | bool swap_uv; |
46 | unsigned int hsub; | 47 | unsigned int hsub; |
47 | unsigned int vsub; | 48 | unsigned int vsub; |
49 | bool alpha; | ||
48 | }; | 50 | }; |
49 | 51 | ||
50 | enum vsp1_pipeline_state { | 52 | enum vsp1_pipeline_state { |
@@ -73,10 +75,12 @@ struct vsp1_pipeline { | |||
73 | 75 | ||
74 | unsigned int num_video; | 76 | unsigned int num_video; |
75 | unsigned int num_inputs; | 77 | unsigned int num_inputs; |
76 | struct vsp1_rwpf *inputs[VPS1_MAX_RPF]; | 78 | struct vsp1_rwpf *inputs[VSP1_MAX_RPF]; |
77 | struct vsp1_rwpf *output; | 79 | struct vsp1_rwpf *output; |
78 | struct vsp1_entity *bru; | 80 | struct vsp1_entity *bru; |
79 | struct vsp1_entity *lif; | 81 | struct vsp1_entity *lif; |
82 | struct vsp1_entity *uds; | ||
83 | struct vsp1_entity *uds_input; | ||
80 | 84 | ||
81 | struct list_head entities; | 85 | struct list_head entities; |
82 | }; | 86 | }; |
@@ -90,7 +94,6 @@ static inline struct vsp1_pipeline *to_vsp1_pipeline(struct media_entity *e) | |||
90 | } | 94 | } |
91 | 95 | ||
92 | struct vsp1_video_buffer { | 96 | struct vsp1_video_buffer { |
93 | struct vsp1_video *video; | ||
94 | struct vb2_buffer buf; | 97 | struct vb2_buffer buf; |
95 | struct list_head queue; | 98 | struct list_head queue; |
96 | 99 | ||
@@ -142,4 +145,8 @@ void vsp1_video_cleanup(struct vsp1_video *video); | |||
142 | 145 | ||
143 | void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe); | 146 | void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe); |
144 | 147 | ||
148 | void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe, | ||
149 | struct vsp1_entity *input, | ||
150 | unsigned int alpha); | ||
151 | |||
145 | #endif /* __VSP1_VIDEO_H__ */ | 152 | #endif /* __VSP1_VIDEO_H__ */ |
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index 1294340dcb36..6e057762c933 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c | |||
@@ -39,22 +39,56 @@ static inline void vsp1_wpf_write(struct vsp1_rwpf *wpf, u32 reg, u32 data) | |||
39 | } | 39 | } |
40 | 40 | ||
41 | /* ----------------------------------------------------------------------------- | 41 | /* ----------------------------------------------------------------------------- |
42 | * Controls | ||
43 | */ | ||
44 | |||
45 | static int wpf_s_ctrl(struct v4l2_ctrl *ctrl) | ||
46 | { | ||
47 | struct vsp1_rwpf *wpf = | ||
48 | container_of(ctrl->handler, struct vsp1_rwpf, ctrls); | ||
49 | u32 value; | ||
50 | |||
51 | if (!vsp1_entity_is_streaming(&wpf->entity)) | ||
52 | return 0; | ||
53 | |||
54 | switch (ctrl->id) { | ||
55 | case V4L2_CID_ALPHA_COMPONENT: | ||
56 | value = vsp1_wpf_read(wpf, VI6_WPF_OUTFMT); | ||
57 | value &= ~VI6_WPF_OUTFMT_PDV_MASK; | ||
58 | value |= ctrl->val << VI6_WPF_OUTFMT_PDV_SHIFT; | ||
59 | vsp1_wpf_write(wpf, VI6_WPF_OUTFMT, value); | ||
60 | break; | ||
61 | } | ||
62 | |||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | static const struct v4l2_ctrl_ops wpf_ctrl_ops = { | ||
67 | .s_ctrl = wpf_s_ctrl, | ||
68 | }; | ||
69 | |||
70 | /* ----------------------------------------------------------------------------- | ||
42 | * V4L2 Subdevice Core Operations | 71 | * V4L2 Subdevice Core Operations |
43 | */ | 72 | */ |
44 | 73 | ||
45 | static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) | 74 | static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) |
46 | { | 75 | { |
76 | struct vsp1_pipeline *pipe = to_vsp1_pipeline(&subdev->entity); | ||
47 | struct vsp1_rwpf *wpf = to_rwpf(subdev); | 77 | struct vsp1_rwpf *wpf = to_rwpf(subdev); |
48 | struct vsp1_pipeline *pipe = | ||
49 | to_vsp1_pipeline(&wpf->entity.subdev.entity); | ||
50 | struct vsp1_device *vsp1 = wpf->entity.vsp1; | 78 | struct vsp1_device *vsp1 = wpf->entity.vsp1; |
51 | const struct v4l2_rect *crop = &wpf->crop; | 79 | const struct v4l2_rect *crop = &wpf->crop; |
52 | unsigned int i; | 80 | unsigned int i; |
53 | u32 srcrpf = 0; | 81 | u32 srcrpf = 0; |
54 | u32 outfmt = 0; | 82 | u32 outfmt = 0; |
83 | int ret; | ||
84 | |||
85 | ret = vsp1_entity_set_streaming(&wpf->entity, enable); | ||
86 | if (ret < 0) | ||
87 | return ret; | ||
55 | 88 | ||
56 | if (!enable) { | 89 | if (!enable) { |
57 | vsp1_write(vsp1, VI6_WPF_IRQ_ENB(wpf->entity.index), 0); | 90 | vsp1_write(vsp1, VI6_WPF_IRQ_ENB(wpf->entity.index), 0); |
91 | vsp1_wpf_write(wpf, VI6_WPF_SRCRPF, 0); | ||
58 | return 0; | 92 | return 0; |
59 | } | 93 | } |
60 | 94 | ||
@@ -99,6 +133,8 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) | |||
99 | 133 | ||
100 | outfmt = fmtinfo->hwfmt << VI6_WPF_OUTFMT_WRFMT_SHIFT; | 134 | outfmt = fmtinfo->hwfmt << VI6_WPF_OUTFMT_WRFMT_SHIFT; |
101 | 135 | ||
136 | if (fmtinfo->alpha) | ||
137 | outfmt |= VI6_WPF_OUTFMT_PXA; | ||
102 | if (fmtinfo->swap_yc) | 138 | if (fmtinfo->swap_yc) |
103 | outfmt |= VI6_WPF_OUTFMT_SPYCS; | 139 | outfmt |= VI6_WPF_OUTFMT_SPYCS; |
104 | if (fmtinfo->swap_uv) | 140 | if (fmtinfo->swap_uv) |
@@ -111,7 +147,13 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) | |||
111 | wpf->entity.formats[RWPF_PAD_SOURCE].code) | 147 | wpf->entity.formats[RWPF_PAD_SOURCE].code) |
112 | outfmt |= VI6_WPF_OUTFMT_CSC; | 148 | outfmt |= VI6_WPF_OUTFMT_CSC; |
113 | 149 | ||
150 | /* Take the control handler lock to ensure that the PDV value won't be | ||
151 | * changed behind our back by a set control operation. | ||
152 | */ | ||
153 | mutex_lock(wpf->ctrls.lock); | ||
154 | outfmt |= vsp1_wpf_read(wpf, VI6_WPF_OUTFMT) & VI6_WPF_OUTFMT_PDV_MASK; | ||
114 | vsp1_wpf_write(wpf, VI6_WPF_OUTFMT, outfmt); | 155 | vsp1_wpf_write(wpf, VI6_WPF_OUTFMT, outfmt); |
156 | mutex_unlock(wpf->ctrls.lock); | ||
115 | 157 | ||
116 | vsp1_write(vsp1, VI6_DPR_WPF_FPORCH(wpf->entity.index), | 158 | vsp1_write(vsp1, VI6_DPR_WPF_FPORCH(wpf->entity.index), |
117 | VI6_DPR_WPF_FPORCH_FP_WPFN); | 159 | VI6_DPR_WPF_FPORCH_FP_WPFN); |
@@ -207,6 +249,20 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) | |||
207 | 249 | ||
208 | vsp1_entity_init_formats(subdev, NULL); | 250 | vsp1_entity_init_formats(subdev, NULL); |
209 | 251 | ||
252 | /* Initialize the control handler. */ | ||
253 | v4l2_ctrl_handler_init(&wpf->ctrls, 1); | ||
254 | v4l2_ctrl_new_std(&wpf->ctrls, &wpf_ctrl_ops, V4L2_CID_ALPHA_COMPONENT, | ||
255 | 0, 255, 1, 255); | ||
256 | |||
257 | wpf->entity.subdev.ctrl_handler = &wpf->ctrls; | ||
258 | |||
259 | if (wpf->ctrls.error) { | ||
260 | dev_err(vsp1->dev, "wpf%u: failed to initialize controls\n", | ||
261 | index); | ||
262 | ret = wpf->ctrls.error; | ||
263 | goto error; | ||
264 | } | ||
265 | |||
210 | /* Initialize the video device. */ | 266 | /* Initialize the video device. */ |
211 | video = &wpf->video; | 267 | video = &wpf->video; |
212 | 268 | ||
@@ -216,7 +272,9 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) | |||
216 | 272 | ||
217 | ret = vsp1_video_init(video, &wpf->entity); | 273 | ret = vsp1_video_init(video, &wpf->entity); |
218 | if (ret < 0) | 274 | if (ret < 0) |
219 | goto error_video; | 275 | goto error; |
276 | |||
277 | wpf->entity.video = video; | ||
220 | 278 | ||
221 | /* Connect the video device to the WPF. All connections are immutable | 279 | /* Connect the video device to the WPF. All connections are immutable |
222 | * except for the WPF0 source link if a LIF is present. | 280 | * except for the WPF0 source link if a LIF is present. |
@@ -229,15 +287,13 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) | |||
229 | RWPF_PAD_SOURCE, | 287 | RWPF_PAD_SOURCE, |
230 | &wpf->video.video.entity, 0, flags); | 288 | &wpf->video.video.entity, 0, flags); |
231 | if (ret < 0) | 289 | if (ret < 0) |
232 | goto error_link; | 290 | goto error; |
233 | 291 | ||
234 | wpf->entity.sink = &wpf->video.video.entity; | 292 | wpf->entity.sink = &wpf->video.video.entity; |
235 | 293 | ||
236 | return wpf; | 294 | return wpf; |
237 | 295 | ||
238 | error_link: | 296 | error: |
239 | vsp1_video_cleanup(video); | 297 | vsp1_entity_destroy(&wpf->entity); |
240 | error_video: | ||
241 | media_entity_cleanup(&wpf->entity.subdev.entity); | ||
242 | return ERR_PTR(ret); | 298 | return ERR_PTR(ret); |
243 | } | 299 | } |