Created
February 5, 2024 10:37
-
-
Save devarsht/22a744d999080de6e813bcfb5a596272 to your computer and use it in GitHub Desktop.
e5010_git_range_diff_v4_to_v4
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1: 13e6e07d2f95 ! 1: 9b5df301ad35 dt-bindings: media: Add bindings for Imagination E5010 JPEG Encoder driver | |
@@ Metadata | |
Author: Devarsh Thakkar <devarsht@ti.com> | |
## Commit message ## | |
- dt-bindings: media: Add bindings for Imagination E5010 JPEG Encoder driver | |
+ media: dt-bindings: Add Imagination E5010 JPEG Encoder | |
- Add dt-bindings for Imagination E5010 JPEG Encoder driver which is | |
- implemented as stateful V4L2 M2M driver. | |
+ Add dt-bindings for Imagination E5010 JPEG Encoder [1] | |
+ which is implemented as stateful V4L2 M2M driver. | |
+ | |
+ The device supports baseline encoding with two different | |
+ quantization tables and compression ratio as demanded. | |
+ | |
+ Minimum resolution supported is 64x64 and | |
+ Maximum resolution supported is 8192x8192. | |
+ | |
+ [1]: AM62A TRM (Section 7.6 is for JPEG Encoder) | |
+ Link: https://www.ti.com/lit/pdf/spruj16 | |
Co-developed-by: David Huang <d-huang@ti.com> | |
Signed-off-by: David Huang <d-huang@ti.com> | |
Signed-off-by: Devarsh Thakkar <devarsht@ti.com> | |
+ --- | |
+ V2: No change | |
+ V3: | |
+ - Add vendor specific compatible | |
+ - Update reg names | |
+ - Update clocks to 1 | |
+ - Fix dts example with proper naming | |
+ V4: | |
+ - Use ti-specific compatible ti,am62a-jpeg-enc as secondary one | |
+ - Update commit message and title | |
+ - Remove clock-names as only single clock | |
+ | |
+ Link to previous commit: | |
+ https://lore.kernel.org/all/20230816152210.4080779-2-devarsht@ti.com/ | |
## Documentation/devicetree/bindings/media/img,e5010-jpeg-enc.yaml (new) ## | |
@@ | |
@@ Documentation/devicetree/bindings/media/img,e5010-jpeg-enc.yaml (new) | |
+ compatible: | |
+ oneOf: | |
+ - items: | |
-+ - const: ti,e5010-jpeg-enc | |
++ - const: ti,am62a-jpeg-enc | |
+ - const: img,e5010-jpeg-enc | |
+ - const: img,e5010-jpeg-enc | |
+ | |
@@ Documentation/devicetree/bindings/media/img,e5010-jpeg-enc.yaml (new) | |
+ clocks: | |
+ maxItems: 1 | |
+ | |
-+ clock-names: | |
-+ items: | |
-+ - const: core_clk | |
-+ | |
+ interrupts: | |
+ maxItems: 1 | |
+ | |
@@ Documentation/devicetree/bindings/media/img,e5010-jpeg-enc.yaml (new) | |
+ - reg-names | |
+ - interrupts | |
+ - clocks | |
-+ - clock-names | |
+ | |
+additionalProperties: false | |
+ | |
@@ Documentation/devicetree/bindings/media/img,e5010-jpeg-enc.yaml (new) | |
+ <0x00 0xfd20200 0x00 0x200>; | |
+ reg-names = "core", "mmu"; | |
+ clocks = <&k3_clks 201 0>; | |
-+ clock-names = "core_clk"; | |
+ power-domains = <&k3_pds 201 TI_SCI_PD_EXCLUSIVE>; | |
+ interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>; | |
+ }; | |
-: ------------ > 2: 17be475ddbb0 media: jpeg: Add reference quantization and huffman tables | |
2: 5f35f30d7cd7 ! 3: 4e08cfba9341 media: imagination: Add E5010 JPEG Encoder driver | |
@@ Commit message | |
All v4l2-compliance tests are passing [2] : | |
v4l2-compliance -s -f -a -d /dev/video0 -e /dev/video1 | |
- Total for e5010 device /dev/video0: 70, Succeeded: 70, Failed: 0, | |
+ Total for e5010 device /dev/video0: 78, Succeeded: 78, Failed: 0, | |
Warnings: 0 | |
+ | |
NOTE: video1 here is VIVID test pattern generator | |
Also tests [3] were run manually to verify below driver features: | |
@@ Commit message | |
TODO: | |
Add MMU and memory tiling support | |
- [1]: AM62A TRM (Section 7.6 is for JPEG Encoder) | |
+ [1]: AM62A TRM (Section 7.6 is for JPEG Encoder) : | |
Link: https://www.ti.com/lit/pdf/spruj16 | |
[2]: v4l2-compliance test : | |
- Link: https://gist.github.com/devarsht/17348fc509fe375a630a798196edbb73 | |
+ Link: https://gist.github.com/devarsht/867b1d646bca3f3877edb1f3638aae31 | |
[3]: E5010 JPEG Encoder Manual tests : | |
- | |
Performance: | |
- Link: https://gist.github.com/devarsht/ef5aba211aae45166681b8b4418d4e65 | |
+ Link: https://gist.github.com/devarsht/63d835093195181866ae9a85de880d3c | |
Functionality: | |
- Link: https://gist.github.com/devarsht/bfef1e3ead8e858b09cbf418aea753e8 | |
+ Link: https://gist.github.com/devarsht/253e485e86661a3051e711f97ec3c5ac | |
Compression Quality: | |
- Link: https://gist.github.com/devarsht/345df9bf7157b4ca094293760e257451 | |
+ Link: https://gist.github.com/devarsht/e16d8b73c8107ac78cc77ad79fd6299f | |
Multi Instance: | |
- Link: https://gist.github.com/devarsht/4b4d734eeb9e0e616837c0836ddbc769 | |
+ Link: https://gist.github.com/devarsht/58af9ccf822963d2bf8f0c2f4481438a | |
+ | |
+ Link: https://gist.github.com/devarsht/ea31179199393c2026ae457219bb6321 | |
Co-developed-by: David Huang <d-huang@ti.com> | |
Signed-off-by: David Huang <d-huang@ti.com> | |
Signed-off-by: Devarsh Thakkar <devarsht@ti.com> | |
+ --- | |
+ V2: | |
+ No change | |
+ | |
+ V3: | |
+ - Correct license headers | |
+ - Use more generic name core instead of jasper for base registers | |
+ - Add Comment for forward declarations | |
+ - Simplify quantization table calculations | |
+ - Use v4l2_apply_frmsize_constraints for updating framesize and remove unrequired functions | |
+ - Place TODO at top of file and in commit message too | |
+ - Use dev_err_probe helper in probe function | |
+ - Fix return value checking for failure scenarios in probe function | |
+ - Use v4l2_err/info/warn helpers instead of dev_err/info/warn helpers | |
+ - Fix unexpected indentation | |
+ - Correct commit message | |
+ - Remove dependency on ARCH_K3 as driver is not specific to that | |
+ | |
+ V4: | |
+ - Fix issue with default params setting | |
+ - Correct v4l2 error prints | |
+ - Simplify register write functions with single statement return values | |
+ - Remove unrequired error checks from get_queue() | |
+ - Drop explicit device_caps setting as it is already taken care by v4l2 | |
+ core | |
+ - Remove unrequired multiplanar checks and memset from s_fmt, g_fmt callback | |
+ functions | |
+ - Fix try_fmt callback to not update the queues | |
+ - Remove unrequired contiguous format attribute from queue_init | |
+ - Use dynamic allocation for video_device and remove unrequired | |
+ assignments in probe() | |
+ - Remove unrequired checks from queue_setup function | |
+ - Return queued buffers back if start_streaming fails | |
+ - Use ARRAY_SIZE in place of hard-coding | |
+ - Use huffman and quantization tables from reference header file | |
+ | |
+ Link to previous commit: | |
+ https://lore.kernel.org/all/20230816152210.4080779-3-devarsht@ti.com/ | |
## MAINTAINERS ## | |
@@ MAINTAINERS: F: drivers/auxdisplay/img-ascii-lcd.c | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc-hw.c (new) | |
+ | |
+int e5010_hw_enable_output_address_error_irq(void __iomem *core_base, u32 enable) | |
+{ | |
-+ int ret; | |
-+ | |
-+ ret = write_reg_field_not_busy(core_base, core_base, | |
++ return write_reg_field_not_busy(core_base, core_base, | |
+ JASPER_INTERRUPT_MASK_OFFSET, | |
+ JASPER_INTERRUPT_MASK_CR_OUTPUT_ADDRESS_ERROR_ENABLE_MASK, | |
+ JASPER_INTERRUPT_MASK_CR_OUTPUT_ADDRESS_ERROR_ENABLE_SHIFT, | |
+ enable); | |
-+ return ret; | |
+} | |
+ | |
+bool e5010_hw_pic_done_irq(void __iomem *core_base) | |
+{ | |
+ u32 reg; | |
-+ bool pic_done; | |
+ | |
+ reg = readl(core_base + JASPER_INTERRUPT_STATUS_OFFSET); | |
-+ pic_done = (reg & JASPER_INTERRUPT_STATUS_CR_PICTURE_DONE_IRQ_MASK) ? true : false; | |
-+ | |
-+ return pic_done; | |
++ return reg & JASPER_INTERRUPT_STATUS_CR_PICTURE_DONE_IRQ_MASK; | |
+} | |
+ | |
+bool e5010_hw_output_address_irq(void __iomem *core_base) | |
+{ | |
+ u32 reg; | |
-+ bool output_address_error; | |
+ | |
+ reg = readl(core_base + JASPER_INTERRUPT_STATUS_OFFSET); | |
-+ output_address_error = (reg & JASPER_INTERRUPT_STATUS_CR_OUTPUT_ADDRESS_ERROR_IRQ_MASK) ? | |
-+ true : false; | |
-+ | |
-+ return output_address_error; | |
++ return reg & JASPER_INTERRUPT_STATUS_CR_OUTPUT_ADDRESS_ERROR_IRQ_MASK; | |
+} | |
+ | |
+int e5010_hw_enable_picture_done_irq(void __iomem *core_base, u32 enable) | |
+{ | |
-+ int ret; | |
-+ | |
-+ ret = write_reg_field_not_busy(core_base, core_base, | |
++ return write_reg_field_not_busy(core_base, core_base, | |
+ JASPER_INTERRUPT_MASK_OFFSET, | |
+ JASPER_INTERRUPT_MASK_CR_PICTURE_DONE_ENABLE_MASK, | |
+ JASPER_INTERRUPT_MASK_CR_PICTURE_DONE_ENABLE_SHIFT, | |
+ enable); | |
-+ return ret; | |
+} | |
+ | |
+int e5010_hw_enable_auto_clock_gating(void __iomem *core_base, u32 enable) | |
+{ | |
-+ int ret; | |
-+ | |
-+ ret = write_reg_field_not_busy(core_base, core_base, | |
++ return write_reg_field_not_busy(core_base, core_base, | |
+ JASPER_CLK_CONTROL_OFFSET, | |
+ JASPER_CLK_CONTROL_CR_JASPER_AUTO_CLKG_ENABLE_MASK, | |
+ JASPER_CLK_CONTROL_CR_JASPER_AUTO_CLKG_ENABLE_SHIFT, | |
+ enable); | |
-+ return ret; | |
+} | |
+ | |
+int e5010_hw_enable_manual_clock_gating(void __iomem *core_base, u32 enable) | |
+{ | |
-+ int ret; | |
-+ | |
-+ ret = write_reg_field_not_busy(core_base, core_base, | |
++ return write_reg_field_not_busy(core_base, core_base, | |
+ JASPER_CLK_CONTROL_OFFSET, | |
+ JASPER_CLK_CONTROL_CR_JASPER_MAN_CLKG_ENABLE_MASK, | |
+ JASPER_CLK_CONTROL_CR_JASPER_MAN_CLKG_ENABLE_SHIFT, 0); | |
-+ return ret; | |
+} | |
+ | |
+int e5010_hw_enable_crc_check(void __iomem *core_base, u32 enable) | |
+{ | |
-+ int ret; | |
-+ | |
-+ ret = write_reg_field_not_busy(core_base, core_base, | |
++ return write_reg_field_not_busy(core_base, core_base, | |
+ JASPER_CRC_CTRL_OFFSET, | |
+ JASPER_CRC_CTRL_JASPER_CRC_ENABLE_MASK, | |
+ JASPER_CRC_CTRL_JASPER_CRC_ENABLE_SHIFT, enable); | |
-+ return ret; | |
+} | |
+ | |
+int e5010_hw_set_input_source_to_memory(void __iomem *core_base, u32 set) | |
+{ | |
-+ int ret; | |
-+ | |
-+ ret = write_reg_field_not_busy(core_base, core_base, | |
++ return write_reg_field_not_busy(core_base, core_base, | |
+ JASPER_INPUT_CTRL0_OFFSET, | |
+ JASPER_INPUT_CTRL0_CR_INPUT_SOURCE_MASK, | |
+ JASPER_INPUT_CTRL0_CR_INPUT_SOURCE_SHIFT, set); | |
-+ return ret; | |
+} | |
+ | |
+int e5010_hw_set_input_luma_addr(void __iomem *core_base, u32 val) | |
+{ | |
-+ int ret; | |
-+ | |
-+ ret = write_reg_field_not_busy(core_base, core_base, | |
++ return write_reg_field_not_busy(core_base, core_base, | |
+ INPUT_LUMA_BASE_OFFSET, | |
+ INPUT_LUMA_BASE_CR_INPUT_LUMA_BASE_MASK, 0, val); | |
-+ return ret; | |
+} | |
+ | |
+int e5010_hw_set_input_chroma_addr(void __iomem *core_base, u32 val) | |
+{ | |
-+ int ret; | |
-+ | |
-+ ret = write_reg_field_not_busy(core_base, core_base, | |
++ return write_reg_field_not_busy(core_base, core_base, | |
+ INPUT_CHROMA_BASE_OFFSET, | |
+ INPUT_CHROMA_BASE_CR_INPUT_CHROMA_BASE_MASK, 0, val); | |
-+ return ret; | |
+} | |
+ | |
+int e5010_hw_set_output_base_addr(void __iomem *core_base, u32 val) | |
+{ | |
-+ int ret; | |
-+ | |
-+ ret = write_reg_field_not_busy(core_base, core_base, | |
++ return write_reg_field_not_busy(core_base, core_base, | |
+ JASPER_OUTPUT_BASE_OFFSET, | |
+ JASPER_OUTPUT_BASE_CR_OUTPUT_BASE_MASK, | |
+ JASPER_OUTPUT_BASE_CR_OUTPUT_BASE_SHIFT, val); | |
-+ return ret; | |
+} | |
+ | |
+int e5010_hw_set_horizontal_size(void __iomem *core_base, u32 val) | |
+{ | |
-+ int ret; | |
-+ | |
-+ ret = write_reg_field_not_busy(core_base, core_base, | |
++ return write_reg_field_not_busy(core_base, core_base, | |
+ JASPER_IMAGE_SIZE_OFFSET, | |
+ JASPER_IMAGE_SIZE_CR_IMAGE_HORIZONTAL_SIZE_MASK, | |
+ JASPER_IMAGE_SIZE_CR_IMAGE_HORIZONTAL_SIZE_SHIFT, | |
+ val); | |
-+ return ret; | |
+} | |
+ | |
+int e5010_hw_set_vertical_size(void __iomem *core_base, u32 val) | |
+{ | |
-+ int ret; | |
-+ | |
-+ ret = write_reg_field_not_busy(core_base, core_base, | |
++ return write_reg_field_not_busy(core_base, core_base, | |
+ JASPER_IMAGE_SIZE_OFFSET, | |
+ JASPER_IMAGE_SIZE_CR_IMAGE_VERTICAL_SIZE_MASK, | |
+ JASPER_IMAGE_SIZE_CR_IMAGE_VERTICAL_SIZE_SHIFT, | |
+ val); | |
-+ return ret; | |
+} | |
+ | |
+int e5010_hw_set_luma_stride(void __iomem *core_base, u32 bytesperline) | |
+{ | |
-+ int ret; | |
+ u32 val = bytesperline / 64; | |
+ | |
-+ ret = write_reg_field_not_busy(core_base, core_base, | |
++ return write_reg_field_not_busy(core_base, core_base, | |
+ JASPER_INPUT_CTRL1_OFFSET, | |
+ JASPER_INPUT_CTRL1_CR_INPUT_LUMA_STRIDE_MASK, | |
+ JASPER_INPUT_CTRL1_CR_INPUT_LUMA_STRIDE_SHIFT, | |
+ val); | |
-+ return ret; | |
+} | |
+ | |
+int e5010_hw_set_chroma_stride(void __iomem *core_base, u32 bytesperline) | |
+{ | |
-+ int ret; | |
+ u32 val = bytesperline / 64; | |
+ | |
-+ ret = write_reg_field_not_busy(core_base, core_base, | |
++ return write_reg_field_not_busy(core_base, core_base, | |
+ JASPER_INPUT_CTRL1_OFFSET, | |
+ JASPER_INPUT_CTRL1_CR_INPUT_CHROMA_STRIDE_MASK, | |
+ JASPER_INPUT_CTRL1_CR_INPUT_CHROMA_STRIDE_SHIFT, | |
+ val); | |
-+ return ret; | |
+} | |
+ | |
+int e5010_hw_set_input_subsampling(void __iomem *core_base, u32 val) | |
+{ | |
-+ int ret; | |
-+ | |
-+ ret = write_reg_field_not_busy(core_base, core_base, | |
++ return write_reg_field_not_busy(core_base, core_base, | |
+ JASPER_INPUT_CTRL0_OFFSET, | |
+ JASPER_INPUT_CTRL0_CR_INPUT_SUBSAMPLING_MASK, | |
+ JASPER_INPUT_CTRL0_CR_INPUT_SUBSAMPLING_SHIFT, | |
+ val); | |
-+ return ret; | |
+} | |
+ | |
+int e5010_hw_set_chroma_order(void __iomem *core_base, u32 val) | |
+{ | |
-+ int ret; | |
-+ | |
-+ ret = write_reg_field_not_busy(core_base, core_base, | |
++ return write_reg_field_not_busy(core_base, core_base, | |
+ JASPER_INPUT_CTRL0_OFFSET, | |
+ JASPER_INPUT_CTRL0_CR_INPUT_CHROMA_ORDER_MASK, | |
+ JASPER_INPUT_CTRL0_CR_INPUT_CHROMA_ORDER_SHIFT, | |
+ val); | |
-+ return ret; | |
+} | |
+ | |
+void e5010_hw_set_output_max_size(void __iomem *core_base, u32 val) | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc-hw.c (new) | |
+ | |
+int e5010_hw_set_qpvalue(void __iomem *core_base, u32 offset, u32 val) | |
+{ | |
-+ int ret; | |
-+ | |
-+ ret = write_reg_field_not_busy(core_base, core_base, offset, 0xffffffff, 0, val); | |
-+ return ret; | |
++ return write_reg_field_not_busy(core_base, core_base, offset, 0xffffffff, 0, val); | |
+} | |
+ | |
+void e5010_hw_clear_output_error(void __iomem *core_base, u32 clear) | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+#include <media/v4l2-event.h> | |
+#include <media/v4l2-ioctl.h> | |
+#include <media/v4l2-mem2mem.h> | |
++#include <media/jpeg-enc-reftables.h> | |
+#include <media/videobuf2-v4l2.h> | |
+#include <media/videobuf2-dma-contig.h> | |
++#include <media/jpeg.h> | |
+#include "e5010-jpeg-enc.h" | |
+#include "e5010-jpeg-enc-hw.h" | |
+ | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+ }, | |
+}; | |
+ | |
-+/* Luma and chroma qp table to acheive 50% compression quality | |
-+ * This is as per example in Annex K.1 of IS0/IEC 10918-1:1994(E) | |
-+ */ | |
-+static const u8 luma[64] = { | |
-+ 16, 11, 10, 16, 24, 40, 51, 61, | |
-+ 12, 12, 14, 19, 26, 58, 60, 55, | |
-+ 14, 13, 16, 24, 40, 57, 69, 56, | |
-+ 14, 17, 22, 29, 51, 87, 80, 62, | |
-+ 18, 22, 37, 56, 68, 109, 103, 77, | |
-+ 24, 35, 55, 64, 81, 104, 113, 92, | |
-+ 49, 64, 78, 87, 103, 121, 120, 101, | |
-+ 72, 92, 95, 98, 112, 100, 103, 99 | |
-+}; | |
-+ | |
-+static const u8 chroma[64] = { | |
-+ 17, 18, 24, 47, 99, 99, 99, 99, | |
-+ 18, 21, 26, 66, 99, 99, 99, 99, | |
-+ 24, 26, 56, 99, 99, 99, 99, 99, | |
-+ 47, 66, 99, 99, 99, 99, 99, 99, | |
-+ 99, 99, 99, 99, 99, 99, 99, 99, | |
-+ 99, 99, 99, 99, 99, 99, 99, 99, | |
-+ 99, 99, 99, 99, 99, 99, 99, 99, | |
-+ 99, 99, 99, 99, 99, 99, 99, 99 | |
-+}; | |
-+ | |
-+/* Zigzag scan pattern */ | |
-+static const u8 zigzag[64] = { | |
-+ 0, 1, 8, 16, 9, 2, 3, 10, | |
-+ 17, 24, 32, 25, 18, 11, 4, 5, | |
-+ 12, 19, 26, 33, 40, 48, 41, 34, | |
-+ 27, 20, 13, 6, 7, 14, 21, 28, | |
-+ 35, 42, 49, 56, 57, 50, 43, 36, | |
-+ 29, 22, 15, 23, 30, 37, 44, 51, | |
-+ 58, 59, 52, 45, 38, 31, 39, 46, | |
-+ 53, 60, 61, 54, 47, 55, 62, 63 | |
-+}; | |
-+ | |
-+/* | |
-+ * Contains the data that needs to be sent in the marker segment of an interchange format JPEG | |
-+ * stream or an abbreviated format table specification data stream. | |
-+ * Specifies the huffman table used for encoding the luminance DC coefficient differences. | |
-+ * The table represents Table K.3 of IS0/IEC 10918-1:1994(E) | |
-+ */ | |
-+static const u8 marker_luma_dc[] = { | |
-+ 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, | |
-+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
-+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B | |
-+}; | |
-+ | |
-+/* | |
-+ * Contains the data that needs to be sent in the marker segment of an interchange format JPEG | |
-+ * stream or an abbreviated format table specification data stream. | |
-+ * Specifies the huffman table used for encoding the luminance AC coefficients. | |
-+ * The table represents Table K.5 of IS0/IEC 10918-1:1994(E) | |
-+ */ | |
-+static const u8 marker_luma_ac[] = { | |
-+ 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, | |
-+ 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, | |
-+ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, | |
-+ 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, | |
-+ 0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25, | |
-+ 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, | |
-+ 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, | |
-+ 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x83, | |
-+ 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, | |
-+ 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, | |
-+ 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, | |
-+ 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, | |
-+ 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA | |
-+}; | |
-+ | |
-+/* | |
-+ * Contains the data that needs to be sent in the marker segment of an interchange format JPEG | |
-+ * stream or an abbreviated format table specification data stream. | |
-+ * Specifies the huffman table used for encoding the chrominance DC coefficient differences. | |
-+ * The table represents Table K.4 of IS0/IEC 10918-1:1994(E) | |
-+ */ | |
-+static const u8 marker_chroma_dc[] = { | |
-+ 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | |
-+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, | |
-+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B | |
-+}; | |
-+ | |
-+/* | |
-+ * Contains the data that needs to be sent in the marker segment of an interchange format JPEG | |
-+ * stream or an abbreviated format table specification data stream. | |
-+ * Specifies the huffman table used for encoding the chrominance AC coefficients. | |
-+ * The table represents Table K.6 of IS0/IEC 10918-1:1994(E) | |
-+ */ | |
-+static const u8 marker_chroma_ac[] = { | |
-+ 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, | |
-+ 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, | |
-+ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, | |
-+ 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, | |
-+ 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, | |
-+ 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, | |
-+ 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, | |
-+ 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, | |
-+ 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, | |
-+ 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, | |
-+ 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, | |
-+ 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, | |
-+ 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA | |
-+}; | |
-+ | |
+static unsigned int debug; | |
+module_param(debug, uint, 0644); | |
+MODULE_PARM_DESC(debug, "debug level"); | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+ | |
+static struct e5010_q_data *get_queue(struct e5010_context *ctx, enum v4l2_buf_type type) | |
+{ | |
-+ switch (type) { | |
-+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: | |
-+ return &ctx->out_queue; | |
-+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: | |
-+ return &ctx->cap_queue; | |
-+ default: | |
-+ return ERR_PTR(-EINVAL); | |
-+ } | |
-+ | |
-+ return ERR_PTR(-EINVAL); | |
++ return (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ? &ctx->out_queue : &ctx->cap_queue; | |
+} | |
+ | |
+static void calculate_qp_tables(struct e5010_context *ctx) | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+ contrast *= INCREASE; | |
+ } | |
+ | |
-+ for (i = 0; i < 64; i++) { | |
-+ long long delta = chroma[i] * contrast + luminosity; | |
-+ int val = (int)(chroma[i] + delta); | |
++ for (i = 0; i < ARRAY_SIZE(luma_q_table); i++) { | |
++ long long delta = chroma_q_table[i] * contrast + luminosity; | |
++ int val = (int)(chroma_q_table[i] + delta); | |
+ | |
+ clamp(val, 1, 255); | |
+ ctx->chroma_qp[i] = quality == -50 ? 1 : val; | |
+ | |
-+ delta = luma[i] * contrast + luminosity; | |
-+ val = (int)(luma[i] + delta); | |
++ delta = luma_q_table[i] * contrast + luminosity; | |
++ val = (int)(luma_q_table[i] + delta); | |
+ clamp(val, 1, 255); | |
+ ctx->luma_qp[i] = quality == -50 ? 1 : val; | |
+ } | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+{ | |
+ strscpy(cap->driver, E5010_MODULE_NAME, sizeof(cap->driver)); | |
+ strscpy(cap->card, E5010_MODULE_NAME, sizeof(cap->card)); | |
-+ snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", E5010_MODULE_NAME); | |
-+ cap->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; | |
-+ cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; | |
+ | |
+ return 0; | |
+} | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+ struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; | |
+ struct v4l2_plane_pix_format *plane_fmt = pix_mp->plane_fmt; | |
+ | |
-+ if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) { | |
-+ v4l2_err(&ctx->e5010->v4l2_dev, "G_FMT with Invalid type: %d\n", f->type); | |
-+ return -EINVAL; | |
-+ } | |
-+ | |
+ queue = get_queue(ctx, f->type); | |
-+ if (IS_ERR(queue)) | |
-+ return PTR_ERR(queue); | |
+ | |
+ pix_mp->flags = 0; | |
+ pix_mp->field = V4L2_FIELD_NONE; | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+static int e5010_jpeg_try_fmt(struct v4l2_format *f, struct e5010_context *ctx) | |
+{ | |
+ struct e5010_fmt *fmt; | |
-+ struct e5010_q_data *queue; | |
-+ int i; | |
+ struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; | |
+ struct v4l2_plane_pix_format *plane_fmt = pix_mp->plane_fmt; | |
+ | |
-+ if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) { | |
-+ v4l2_err(&ctx->e5010->v4l2_dev, "G_FMT with Invalid type: %d\n", f->type); | |
-+ return -EINVAL; | |
-+ } | |
-+ | |
+ fmt = find_format(f); | |
+ if (!fmt) { | |
+ if (V4L2_TYPE_IS_OUTPUT(f->type)) | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+ return -EINVAL; | |
+ } | |
+ | |
-+ queue = get_queue(ctx, f->type); | |
-+ if (IS_ERR(queue)) | |
-+ return PTR_ERR(queue); | |
-+ | |
-+ queue->fmt = fmt; | |
-+ queue->width = pix_mp->width; | |
-+ queue->height = pix_mp->height; | |
-+ | |
+ if (V4L2_TYPE_IS_OUTPUT(f->type)) { | |
+ if (!pix_mp->colorspace) | |
+ pix_mp->colorspace = V4L2_COLORSPACE_JPEG; | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+ v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat, | |
+ pix_mp->width, pix_mp->height); | |
+ | |
-+ for (i = 0; i < fmt->num_planes; i++) { | |
-+ queue->bytesperline[i] = plane_fmt[i].bytesperline; | |
-+ queue->sizeimage[i] = plane_fmt[i].sizeimage; | |
-+ } | |
+ } else { | |
+ pix_mp->colorspace = V4L2_COLORSPACE_JPEG; | |
+ pix_mp->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; | |
+ pix_mp->quantization = V4L2_QUANTIZATION_DEFAULT; | |
+ pix_mp->xfer_func = V4L2_XFER_FUNC_DEFAULT; | |
-+ memset(plane_fmt[0].reserved, 0, sizeof(plane_fmt[0].reserved)); | |
+ v4l2_apply_frmsize_constraints(&pix_mp->width, | |
+ &pix_mp->height, | |
+ &fmt->frmsize); | |
-+ queue->sizeimage[0] = pix_mp->width * pix_mp->height * JPEG_MAX_BYTES_PER_PIXEL; | |
-+ queue->sizeimage[0] += HEADER_SIZE; | |
-+ queue->sizeimage[1] = 0; | |
-+ queue->bytesperline[0] = 0; | |
-+ queue->bytesperline[1] = 0; | |
-+ plane_fmt[0].sizeimage = queue->sizeimage[0]; | |
++ plane_fmt[0].sizeimage = pix_mp->width * pix_mp->height * JPEG_MAX_BYTES_PER_PIXEL; | |
++ plane_fmt[0].sizeimage += HEADER_SIZE; | |
+ plane_fmt[0].bytesperline = 0; | |
++ pix_mp->pixelformat = fmt->fourcc; | |
++ pix_mp->num_planes = fmt->num_planes; | |
+ } | |
+ pix_mp->flags = 0; | |
+ pix_mp->field = V4L2_FIELD_NONE; | |
-+ pix_mp->pixelformat = fmt->fourcc; | |
-+ queue->width_adjusted = pix_mp->width; | |
-+ queue->height_adjusted = pix_mp->height; | |
-+ pix_mp->num_planes = fmt->num_planes; | |
-+ memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved)); | |
+ | |
+ dprintk(ctx->e5010, 2, | |
+ "ctx: 0x%p: format type %s:, wxh: %dx%d (plane0 : %d bytes, plane1 : %d bytes),fmt: %c%c%c%c\n", | |
-+ ctx, type_name(f->type), queue->width_adjusted, queue->height_adjusted, | |
-+ queue->sizeimage[0], queue->sizeimage[1], | |
-+ (queue->fmt->fourcc & 0xff), | |
-+ (queue->fmt->fourcc >> 8) & 0xff, | |
-+ (queue->fmt->fourcc >> 16) & 0xff, | |
-+ (queue->fmt->fourcc >> 24) & 0xff); | |
++ ctx, type_name(f->type), pix_mp->width, pix_mp->height, | |
++ plane_fmt[0].sizeimage, plane_fmt[1].sizeimage, | |
++ (fmt->fourcc & 0xff), | |
++ (fmt->fourcc >> 8) & 0xff, | |
++ (fmt->fourcc >> 16) & 0xff, | |
++ (fmt->fourcc >> 24) & 0xff); | |
+ | |
+ return 0; | |
+} | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+{ | |
+ struct e5010_context *ctx = file->private_data; | |
+ struct vb2_queue *vq; | |
++ int ret = 0, i = 0; | |
++ struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; | |
++ struct v4l2_plane_pix_format *plane_fmt = pix_mp->plane_fmt; | |
++ struct e5010_q_data *queue; | |
++ struct e5010_fmt *fmt; | |
+ | |
+ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); | |
+ if (!vq) | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+ return -EBUSY; | |
+ } | |
+ | |
-+ return e5010_jpeg_try_fmt(f, ctx); | |
++ ret = e5010_jpeg_try_fmt(f, ctx); | |
++ if (ret) | |
++ return ret; | |
++ | |
++ fmt = find_format(f); | |
++ queue = get_queue(ctx, f->type); | |
++ | |
++ queue->fmt = fmt; | |
++ queue->width = pix_mp->width; | |
++ queue->height = pix_mp->height; | |
++ | |
++ if (V4L2_TYPE_IS_OUTPUT(f->type)) { | |
++ for (i = 0; i < fmt->num_planes; i++) { | |
++ queue->bytesperline[i] = plane_fmt[i].bytesperline; | |
++ queue->sizeimage[i] = plane_fmt[i].sizeimage; | |
++ } | |
++ } else { | |
++ queue->sizeimage[0] = plane_fmt[0].sizeimage; | |
++ queue->sizeimage[1] = 0; | |
++ queue->bytesperline[0] = 0; | |
++ queue->bytesperline[1] = 0; | |
++ } | |
++ | |
++ return 0; | |
+} | |
+ | |
+static int e5010_enum_framesizes(struct file *file, void *priv, struct v4l2_frmsizeenum *fsize) | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+ return -EINVAL; | |
+ | |
+ queue = get_queue(ctx, s->type); | |
-+ if (IS_ERR(queue)) | |
-+ return PTR_ERR(queue); | |
+ | |
+ switch (s->target) { | |
+ case V4L2_SEL_TGT_CROP_DEFAULT: | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+ return -EINVAL; | |
+ | |
+ queue = get_queue(ctx, s->type); | |
-+ if (IS_ERR(queue)) | |
-+ return PTR_ERR(queue); | |
+ | |
+ queue->crop.left = 0; | |
+ queue->crop.top = 0; | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+ /* src_vq */ | |
+ memset(src_vq, 0, sizeof(*src_vq)); | |
+ src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | |
-+ src_vq->dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS; | |
+ src_vq->io_modes = VB2_MMAP | VB2_DMABUF; | |
+ src_vq->drv_priv = ctx; | |
+ src_vq->buf_struct_size = sizeof(struct e5010_buffer); | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+ /* dst_vq */ | |
+ memset(dst_vq, 0, sizeof(*dst_vq)); | |
+ dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | |
-+ src_vq->dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS; | |
+ dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; | |
+ dst_vq->drv_priv = ctx; | |
+ dst_vq->buf_struct_size = sizeof(struct e5010_buffer); | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+ calculate_qp_tables(ctx); | |
+ break; | |
+ default: | |
-+ v4l2_err(&ctx->e5010->v4l2_dev, "Invalid control, id = %d, val = %d\n", | |
-+ ctrl->id, ctrl->val); | |
+ return -EINVAL; | |
+ } | |
+ | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+ queue->fmt = fmt; | |
+ queue->width = DEFAULT_WIDTH; | |
+ queue->height = DEFAULT_HEIGHT; | |
++ pix_mp->width = queue->width; | |
++ pix_mp->height = queue->height; | |
+ v4l2_apply_frmsize_constraints(&pix_mp->width, | |
+ &pix_mp->height, | |
+ &fmt->frmsize); | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+ queue->fmt = fmt; | |
+ queue->width = DEFAULT_WIDTH; | |
+ queue->height = DEFAULT_HEIGHT; | |
++ pix_mp->width = queue->width; | |
++ pix_mp->height = queue->height; | |
+ v4l2_apply_frmsize_constraints(&pix_mp->width, | |
+ &pix_mp->height, | |
+ &fmt->frmsize); | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+ return 0; | |
+} | |
+ | |
-+static struct video_device e5010_videodev = { | |
-+ .name = E5010_MODULE_NAME, | |
-+ .fops = &e5010_fops, | |
-+ .ioctl_ops = &e5010_ioctl_ops, | |
-+ .minor = -1, | |
-+ .release = video_device_release_empty, | |
-+ .vfl_dir = VFL_DIR_M2M, | |
-+ .device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING, | |
-+}; | |
-+ | |
+static void header_write(struct e5010_context *ctx, u8 *addr, unsigned int *offset, | |
+ unsigned int no_bytes, unsigned long bits) | |
+{ | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+ /* Huffman tables */ | |
+ header_write(ctx, buffer, offset, 2, DHT_MARKER); | |
+ header_write(ctx, buffer, offset, 2, LH_DC); | |
-+ for (i = 0 ; i < (LH_DC - 2); i++) | |
-+ header_write(ctx, buffer, offset, 1, marker_luma_dc[i]); | |
++ header_write(ctx, buffer, offset, 1, JPEG_LUM_HT | JPEG_DC_HT); | |
++ for (i = 0 ; i < ARRAY_SIZE(luma_dc_table); i++) | |
++ header_write(ctx, buffer, offset, 1, luma_dc_table[i]); | |
+ | |
+ header_write(ctx, buffer, offset, 2, DHT_MARKER); | |
+ header_write(ctx, buffer, offset, 2, LH_AC); | |
-+ for (i = 0 ; i < (LH_AC - 2); i++) | |
-+ header_write(ctx, buffer, offset, 1, marker_luma_ac[i]); | |
++ header_write(ctx, buffer, offset, 1, JPEG_LUM_HT | JPEG_AC_HT); | |
++ for (i = 0 ; i < ARRAY_SIZE(luma_ac_table); i++) | |
++ header_write(ctx, buffer, offset, 1, luma_ac_table[i]); | |
+ | |
+ header_write(ctx, buffer, offset, 2, DHT_MARKER); | |
+ header_write(ctx, buffer, offset, 2, LH_DC); | |
-+ for (i = 0 ; i < (LH_DC - 2); i++) | |
-+ header_write(ctx, buffer, offset, 1, marker_chroma_dc[i]); | |
++ header_write(ctx, buffer, offset, 1, JPEG_CHR_HT | JPEG_DC_HT); | |
++ for (i = 0 ; i < ARRAY_SIZE(chroma_dc_table); i++) | |
++ header_write(ctx, buffer, offset, 1, chroma_dc_table[i]); | |
+ | |
+ header_write(ctx, buffer, offset, 2, DHT_MARKER); | |
+ header_write(ctx, buffer, offset, 2, LH_AC); | |
-+ for (i = 0 ; i < (LH_AC - 2); i++) | |
-+ header_write(ctx, buffer, offset, 1, marker_chroma_ac[i]); | |
++ header_write(ctx, buffer, offset, 1, JPEG_CHR_HT | JPEG_AC_HT); | |
++ for (i = 0 ; i < ARRAY_SIZE(chroma_ac_table); i++) | |
++ header_write(ctx, buffer, offset, 1, chroma_ac_table[i]); | |
+} | |
+ | |
+static void encode_frame_header(struct e5010_context *ctx, void *addr, unsigned int *offset) | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+ mutex_init(&e5010->mutex); | |
+ spin_lock_init(&e5010->hw_lock); | |
+ | |
-+ e5010->vdev = &e5010_videodev; | |
++ e5010->vdev = video_device_alloc(); | |
++ if (!e5010->vdev) { | |
++ dev_err(e5010->dev, "failed to allocate video device\n"); | |
++ return -ENOMEM; | |
++ } | |
++ | |
++ snprintf(e5010->vdev->name, sizeof(e5010->vdev->name), "%s", E5010_MODULE_NAME); | |
++ e5010->vdev->fops = &e5010_fops; | |
++ e5010->vdev->ioctl_ops = &e5010_ioctl_ops; | |
++ e5010->vdev->minor = -1; | |
++ e5010->vdev->release = video_device_release; | |
++ e5010->vdev->vfl_dir = VFL_DIR_M2M; | |
++ e5010->vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; | |
+ e5010->vdev->v4l2_dev = &e5010->v4l2_dev; | |
+ e5010->vdev->lock = &e5010->mutex; | |
-+ e5010->vdev->queue = NULL; | |
-+ e5010->vdev->prio = NULL; | |
-+ e5010->vdev->dev_parent = NULL; | |
-+ e5010->vdev->minor = -1; | |
+ | |
+ ret = v4l2_device_register(&pdev->dev, &e5010->v4l2_dev); | |
+ if (ret) | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+ | |
+ video_set_drvdata(e5010->vdev, e5010); | |
+ | |
-+ ret = video_register_device(e5010->vdev, VFL_TYPE_VIDEO, 0); | |
-+ if (ret) { | |
-+ dev_err_probe(e5010->dev, ret, "failed to register video device\n"); | |
-+ goto fail_after_v4l2_register; | |
-+ } | |
-+ | |
-+ v4l2_info(&e5010->v4l2_dev, "Device registered as /dev/video%d\n", | |
-+ e5010->vdev->num); | |
-+ | |
+ e5010->core_base = devm_platform_ioremap_resource_byname(pdev, "core"); | |
+ if (IS_ERR(e5010->core_base)) { | |
+ ret = PTR_ERR(e5010->core_base); | |
+ dev_err_probe(e5010->dev, ret, "Missing 'core' resources area\n"); | |
-+ goto fail_after_video_register_device; | |
++ goto fail_after_v4l2_register; | |
+ } | |
+ | |
+ e5010->mmu_base = devm_platform_ioremap_resource_byname(pdev, "mmu"); | |
+ if (IS_ERR(e5010->mmu_base)) { | |
+ ret = PTR_ERR(e5010->mmu_base); | |
+ dev_err_probe(e5010->dev, ret, "Missing 'mmu' resources area\n"); | |
-+ goto fail_after_video_register_device; | |
++ goto fail_after_v4l2_register; | |
+ } | |
+ | |
+ e5010->last_context_run = NULL; | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+ E5010_MODULE_NAME, e5010); | |
+ if (ret) { | |
+ dev_err_probe(e5010->dev, ret, "failed to register IRQ %d\n", irq); | |
-+ goto fail_after_video_register_device; | |
++ goto fail_after_v4l2_register; | |
+ } | |
+ | |
-+ e5010->clk = devm_clk_get(&pdev->dev, "core_clk"); | |
++ e5010->clk = devm_clk_get(&pdev->dev, NULL); | |
+ if (IS_ERR(e5010->clk)) { | |
+ ret = PTR_ERR(e5010->clk); | |
+ dev_err_probe(e5010->dev, ret, "failed to get clock\n"); | |
-+ goto fail_after_video_register_device; | |
++ goto fail_after_v4l2_register; | |
+ } | |
+ | |
+ pm_runtime_enable(e5010->dev); | |
+ | |
++ ret = video_register_device(e5010->vdev, VFL_TYPE_VIDEO, 0); | |
++ if (ret) { | |
++ dev_err_probe(e5010->dev, ret, "failed to register video device\n"); | |
++ goto fail_after_video_register_device; | |
++ } | |
++ | |
++ v4l2_info(&e5010->v4l2_dev, "Device registered as /dev/video%d\n", | |
++ e5010->vdev->num); | |
++ | |
+ return 0; | |
+ | |
+fail_after_video_register_device: | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+ return 0; | |
+} | |
+ | |
++static void e5010_vb2_buffers_return(struct vb2_queue *q, enum vb2_buffer_state state) | |
++{ | |
++ struct vb2_v4l2_buffer *vbuf; | |
++ struct e5010_context *ctx = vb2_get_drv_priv(q); | |
++ | |
++ if (V4L2_TYPE_IS_OUTPUT(q->type)) { | |
++ while ((vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx))) { | |
++ dprintk(ctx->e5010, 2, "ctx: 0x%p, buf type %s | index %d\n", | |
++ ctx, type_name(vbuf->vb2_buf.type), vbuf->vb2_buf.index); | |
++ v4l2_m2m_buf_done(vbuf, state); | |
++ } | |
++ } else { | |
++ while ((vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx))) { | |
++ dprintk(ctx->e5010, 2, "ctx: 0x%p, buf type %s | index %d\n", | |
++ ctx, type_name(vbuf->vb2_buf.type), vbuf->vb2_buf.index); | |
++ vb2_set_plane_payload(&vbuf->vb2_buf, 0, 0); | |
++ v4l2_m2m_buf_done(vbuf, state); | |
++ } | |
++ } | |
++} | |
++ | |
+static int e5010_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, | |
+ unsigned int sizes[], struct device *alloc_devs[]) | |
+{ | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+ struct e5010_q_data *queue; | |
+ int i; | |
+ | |
-+ if (!V4L2_TYPE_IS_MULTIPLANAR(vq->type)) { | |
-+ v4l2_err(&ctx->e5010->v4l2_dev, "queue setup with Invalid type: %d\n", vq->type); | |
-+ return -EINVAL; | |
-+ } | |
-+ | |
+ queue = get_queue(ctx, vq->type); | |
-+ if (IS_ERR(queue)) | |
-+ return PTR_ERR(queue); | |
+ | |
+ if (*nplanes) { | |
+ if (*nplanes != queue->fmt->num_planes) | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+ return 0; | |
+ } | |
+ | |
-+ *nbuffers = max_t(unsigned int, *nbuffers, 1); | |
+ *nplanes = queue->fmt->num_planes; | |
+ for (i = 0; i < *nplanes; i++) | |
+ sizes[i] = queue->sizeimage[i]; | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+ vbuf->field = V4L2_FIELD_NONE; | |
+ | |
+ queue = get_queue(ctx, vb->vb2_queue->type); | |
-+ if (IS_ERR(queue)) | |
-+ return PTR_ERR(queue); | |
+ | |
+ for (i = 0; i < queue->fmt->num_planes; i++) { | |
+ if (vb2_plane_size(vb, i) < (unsigned long)queue->sizeimage[i]) { | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+ v4l2_m2m_dst_buf_is_last(ctx->fh.m2m_ctx)) { | |
+ struct e5010_q_data *queue = get_queue(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); | |
+ | |
-+ if (IS_ERR(queue)) | |
-+ return; | |
-+ | |
+ vbuf->sequence = queue->sequence++; | |
+ v4l2_m2m_last_buffer_done(ctx->fh.m2m_ctx, vbuf); | |
+ v4l2_event_queue_fh(&ctx->fh, &e5010_eos_event); | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+ | |
+ struct e5010_q_data *queue = get_queue(ctx, q->type); | |
+ | |
-+ if (IS_ERR(queue)) | |
-+ return PTR_ERR(queue); | |
+ queue->streaming = true; | |
+ v4l2_m2m_update_start_streaming_state(ctx->fh.m2m_ctx, q); | |
+ queue->sequence = 0; | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+ ret = pm_runtime_resume_and_get(ctx->e5010->dev); | |
+ if (ret < 0) { | |
+ v4l2_err(&ctx->e5010->v4l2_dev, "failed to power up jpeg\n"); | |
-+ return ret; | |
++ goto fail; | |
+ } | |
+ | |
+ ret = e5010_init_device(ctx->e5010); | |
-+ if (ret) | |
++ if (ret) { | |
+ v4l2_err(&ctx->e5010->v4l2_dev, "failed to Enable e5010 device\n"); | |
++ goto fail; | |
++ } | |
++ | |
++ return 0; | |
++ | |
++fail: | |
++ e5010_vb2_buffers_return(q, VB2_BUF_STATE_QUEUED); | |
+ | |
+ return ret; | |
+} | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+static void e5010_stop_streaming(struct vb2_queue *q) | |
+{ | |
+ struct e5010_context *ctx = vb2_get_drv_priv(q); | |
-+ struct vb2_v4l2_buffer *vbuf; | |
+ struct e5010_q_data *queue; | |
+ | |
+ queue = get_queue(ctx, q->type); | |
-+ if (IS_ERR(queue)) | |
-+ return; | |
+ | |
+ queue->streaming = false; | |
+ | |
-+ if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | |
-+ while ((vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx))) { | |
-+ dprintk(ctx->e5010, 2, "ctx: 0x%p, buf type %s | index %d\n", | |
-+ ctx, type_name(vbuf->vb2_buf.type), vbuf->vb2_buf.index); | |
-+ v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR); | |
-+ } | |
-+ } else { | |
-+ while ((vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx))) { | |
-+ dprintk(ctx->e5010, 2, "ctx: 0x%p, buf type %s | index %d\n", | |
-+ ctx, type_name(vbuf->vb2_buf.type), vbuf->vb2_buf.index); | |
-+ vb2_set_plane_payload(&vbuf->vb2_buf, 0, 0); | |
-+ v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR); | |
-+ } | |
-+ } | |
++ e5010_vb2_buffers_return(q, VB2_BUF_STATE_ERROR); | |
+ | |
+ if (V4L2_TYPE_IS_OUTPUT(q->type)) | |
+ v4l2_m2m_update_stop_streaming_state(ctx->fh.m2m_ctx, q); | |
@@ drivers/media/platform/imagination/e5010-jpeg-enc.c (new) | |
+ reg += HEADER_SIZE; | |
+ ret = e5010_hw_set_output_base_addr(e5010->core_base, reg); | |
+ if (ret || !reg) { | |
-+ v4l2_err(&e5010->v4l2_dev, "failed to set output size\n"); | |
++ v4l2_err(&e5010->v4l2_dev, "failed to set output base address\n"); | |
+ goto device_busy_err; | |
+ } | |
+ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment