Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[media] s5p-jpeg: add support for 5433

JPEG IP found in Exynos5433 is similar to what is in Exynos4, but
there are some subtle differences which this patch takes into account.

The most important difference is in what is processed by the JPEG IP and
what has to be provided to it. In case of 5433 the IP does not parse
Huffman and quantisation tables, so this has to be performed with the CPU
and the majority of the code in this patch does that.

A small but important difference is in what address is passed to the JPEG
IP. In case of 5433 it is the SOS (start of scan) position, which is
natural, because the headers must be parsed elsewhere.

There is also a difference in how the hardware is put to work in
device_run.

Data structures are extended as appropriate to accommodate the above
changes.

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
Reviewed-by: Jacek Anaszewski <j.anaszewski@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>

authored by

Andrzej Pietrasiewicz and committed by
Mauro Carvalho Chehab
6c96dbbc b95a24d6

+517 -61
+2 -1
Documentation/devicetree/bindings/media/exynos-jpeg-codec.txt
··· 4 4 5 5 - compatible : should be one of: 6 6 "samsung,s5pv210-jpeg", "samsung,exynos4210-jpeg", 7 - "samsung,exynos3250-jpeg", "samsung,exynos5420-jpeg"; 7 + "samsung,exynos3250-jpeg", "samsung,exynos5420-jpeg", 8 + "samsung,exynos5433-jpeg"; 8 9 - reg : address and length of the JPEG codec IP register set; 9 10 - interrupts : specifies the JPEG codec IP interrupt; 10 11 - clock-names : should contain:
+359 -19
drivers/media/platform/s5p-jpeg/jpeg-core.c
··· 626 626 return V4L2_JPEG_CHROMA_SUBSAMPLING_411; 627 627 return exynos3250_decoded_subsampling[ctx->subsampling]; 628 628 case SJPEG_EXYNOS4: 629 + case SJPEG_EXYNOS5433: 629 630 if (ctx->subsampling > 2) 630 631 return V4L2_JPEG_CHROMA_SUBSAMPLING_420; 631 632 return exynos4x12_decoded_subsampling[ctx->subsampling]; ··· 749 748 ARRAY_SIZE(hactblg0)); 750 749 exynos4_jpeg_set_tbl(base, hactblg0, EXYNOS4_HUFF_TBL_HACCV, 751 750 ARRAY_SIZE(hactblg0)); 751 + } 752 + 753 + static inline int __exynos4_huff_tbl(int class, int id, bool lenval) 754 + { 755 + /* 756 + * class: 0 - DC, 1 - AC 757 + * id: 0 - Y, 1 - Cb/Cr 758 + */ 759 + if (class) { 760 + if (id) 761 + return lenval ? EXYNOS4_HUFF_TBL_HACCL : 762 + EXYNOS4_HUFF_TBL_HACCV; 763 + return lenval ? EXYNOS4_HUFF_TBL_HACLL : EXYNOS4_HUFF_TBL_HACLV; 764 + 765 + } 766 + /* class == 0 */ 767 + if (id) 768 + return lenval ? EXYNOS4_HUFF_TBL_HDCCL : EXYNOS4_HUFF_TBL_HDCCV; 769 + 770 + return lenval ? EXYNOS4_HUFF_TBL_HDCLL : EXYNOS4_HUFF_TBL_HDCLV; 771 + } 772 + 773 + static inline int exynos4_huff_tbl_len(int class, int id) 774 + { 775 + return __exynos4_huff_tbl(class, id, true); 776 + } 777 + 778 + static inline int exynos4_huff_tbl_val(int class, int id) 779 + { 780 + return __exynos4_huff_tbl(class, id, false); 781 + } 782 + 783 + static int get_byte(struct s5p_jpeg_buffer *buf); 784 + static int get_word_be(struct s5p_jpeg_buffer *buf, unsigned int *word); 785 + static void skip(struct s5p_jpeg_buffer *buf, long len); 786 + 787 + static void exynos4_jpeg_parse_decode_h_tbl(struct s5p_jpeg_ctx *ctx) 788 + { 789 + struct s5p_jpeg *jpeg = ctx->jpeg; 790 + struct vb2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); 791 + struct s5p_jpeg_buffer jpeg_buffer; 792 + unsigned int word; 793 + int c, x, components; 794 + 795 + jpeg_buffer.size = 2; /* Ls */ 796 + jpeg_buffer.data = 797 + (unsigned long)vb2_plane_vaddr(vb, 0) + ctx->out_q.sos + 2; 798 + jpeg_buffer.curr = 0; 799 + 800 + word = 0; 801 + 802 + if (get_word_be(&jpeg_buffer, &word)) 803 + return; 804 + jpeg_buffer.size = (long)word - 2; 805 + jpeg_buffer.data += 2; 806 + jpeg_buffer.curr = 0; 807 + 808 + components = get_byte(&jpeg_buffer); 809 + if (components == -1) 810 + return; 811 + while (components--) { 812 + c = get_byte(&jpeg_buffer); 813 + if (c == -1) 814 + return; 815 + x = get_byte(&jpeg_buffer); 816 + if (x == -1) 817 + return; 818 + exynos4_jpeg_select_dec_h_tbl(jpeg->regs, c, 819 + (((x >> 4) & 0x1) << 1) | (x & 0x1)); 820 + } 821 + 822 + } 823 + 824 + static void exynos4_jpeg_parse_huff_tbl(struct s5p_jpeg_ctx *ctx) 825 + { 826 + struct s5p_jpeg *jpeg = ctx->jpeg; 827 + struct vb2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); 828 + struct s5p_jpeg_buffer jpeg_buffer; 829 + unsigned int word; 830 + int c, i, n, j; 831 + 832 + for (j = 0; j < ctx->out_q.dht.n; ++j) { 833 + jpeg_buffer.size = ctx->out_q.dht.len[j]; 834 + jpeg_buffer.data = (unsigned long)vb2_plane_vaddr(vb, 0) + 835 + ctx->out_q.dht.marker[j]; 836 + jpeg_buffer.curr = 0; 837 + 838 + word = 0; 839 + while (jpeg_buffer.curr < jpeg_buffer.size) { 840 + char id, class; 841 + 842 + c = get_byte(&jpeg_buffer); 843 + if (c == -1) 844 + return; 845 + id = c & 0xf; 846 + class = (c >> 4) & 0xf; 847 + n = 0; 848 + for (i = 0; i < 16; ++i) { 849 + c = get_byte(&jpeg_buffer); 850 + if (c == -1) 851 + return; 852 + word |= c << ((i % 4) * 8); 853 + if ((i + 1) % 4 == 0) { 854 + writel(word, jpeg->regs + 855 + exynos4_huff_tbl_len(class, id) + 856 + (i / 4) * 4); 857 + word = 0; 858 + } 859 + n += c; 860 + } 861 + word = 0; 862 + for (i = 0; i < n; ++i) { 863 + c = get_byte(&jpeg_buffer); 864 + if (c == -1) 865 + return; 866 + word |= c << ((i % 4) * 8); 867 + if ((i + 1) % 4 == 0) { 868 + writel(word, jpeg->regs + 869 + exynos4_huff_tbl_val(class, id) + 870 + (i / 4) * 4); 871 + word = 0; 872 + } 873 + } 874 + if (i % 4) { 875 + writel(word, jpeg->regs + 876 + exynos4_huff_tbl_val(class, id) + (i / 4) * 4); 877 + } 878 + word = 0; 879 + } 880 + } 881 + } 882 + 883 + static void exynos4_jpeg_parse_decode_q_tbl(struct s5p_jpeg_ctx *ctx) 884 + { 885 + struct s5p_jpeg *jpeg = ctx->jpeg; 886 + struct vb2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); 887 + struct s5p_jpeg_buffer jpeg_buffer; 888 + unsigned int word; 889 + int c, x, components; 890 + 891 + jpeg_buffer.size = ctx->out_q.sof_len; 892 + jpeg_buffer.data = 893 + (unsigned long)vb2_plane_vaddr(vb, 0) + ctx->out_q.sof; 894 + jpeg_buffer.curr = 0; 895 + 896 + word = 0; 897 + 898 + skip(&jpeg_buffer, 5); /* P, Y, X */ 899 + components = get_byte(&jpeg_buffer); 900 + if (components == -1) 901 + return; 902 + 903 + exynos4_jpeg_set_dec_components(jpeg->regs, components); 904 + 905 + while (components--) { 906 + c = get_byte(&jpeg_buffer); 907 + if (c == -1) 908 + return; 909 + skip(&jpeg_buffer, 1); 910 + x = get_byte(&jpeg_buffer); 911 + if (x == -1) 912 + return; 913 + exynos4_jpeg_select_dec_q_tbl(jpeg->regs, c, x); 914 + } 915 + } 916 + 917 + static void exynos4_jpeg_parse_q_tbl(struct s5p_jpeg_ctx *ctx) 918 + { 919 + struct s5p_jpeg *jpeg = ctx->jpeg; 920 + struct vb2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); 921 + struct s5p_jpeg_buffer jpeg_buffer; 922 + unsigned int word; 923 + int c, i, j; 924 + 925 + for (j = 0; j < ctx->out_q.dqt.n; ++j) { 926 + jpeg_buffer.size = ctx->out_q.dqt.len[j]; 927 + jpeg_buffer.data = (unsigned long)vb2_plane_vaddr(vb, 0) + 928 + ctx->out_q.dqt.marker[j]; 929 + jpeg_buffer.curr = 0; 930 + 931 + word = 0; 932 + while (jpeg_buffer.size - jpeg_buffer.curr >= 65) { 933 + char id; 934 + 935 + c = get_byte(&jpeg_buffer); 936 + if (c == -1) 937 + return; 938 + id = c & 0xf; 939 + /* nonzero means extended mode - not supported */ 940 + if ((c >> 4) & 0xf) 941 + return; 942 + for (i = 0; i < 64; ++i) { 943 + c = get_byte(&jpeg_buffer); 944 + if (c == -1) 945 + return; 946 + word |= c << ((i % 4) * 8); 947 + if ((i + 1) % 4 == 0) { 948 + writel(word, jpeg->regs + 949 + EXYNOS4_QTBL_CONTENT(id) + (i / 4) * 4); 950 + word = 0; 951 + } 952 + } 953 + word = 0; 954 + } 955 + } 752 956 } 753 957 754 958 /* ··· 1100 894 unsigned long buffer, unsigned long size, 1101 895 struct s5p_jpeg_ctx *ctx) 1102 896 { 1103 - int c, components = 0, notfound; 1104 - unsigned int height, width, word, subsampling = 0; 897 + int c, components = 0, notfound, n_dht = 0, n_dqt = 0; 898 + unsigned int height, width, word, subsampling = 0, sos = 0, sof = 0, 899 + sof_len = 0; 900 + unsigned int dht[S5P_JPEG_MAX_MARKER], dht_len[S5P_JPEG_MAX_MARKER], 901 + dqt[S5P_JPEG_MAX_MARKER], dqt_len[S5P_JPEG_MAX_MARKER]; 1105 902 long length; 1106 903 struct s5p_jpeg_buffer jpeg_buffer; 1107 904 ··· 1113 904 jpeg_buffer.curr = 0; 1114 905 1115 906 notfound = 1; 1116 - while (notfound) { 907 + while (notfound || !sos) { 1117 908 c = get_byte(&jpeg_buffer); 1118 909 if (c == -1) 1119 910 return false; ··· 1132 923 case SOF0: 1133 924 if (get_word_be(&jpeg_buffer, &word)) 1134 925 break; 926 + length = (long)word - 2; 927 + if (!length) 928 + return false; 929 + sof = jpeg_buffer.curr; /* after 0xffc0 */ 930 + sof_len = length; 1135 931 if (get_byte(&jpeg_buffer) == -1) 1136 932 break; 1137 933 if (get_word_be(&jpeg_buffer, &height)) ··· 1146 932 components = get_byte(&jpeg_buffer); 1147 933 if (components == -1) 1148 934 break; 1149 - notfound = 0; 1150 935 1151 936 if (components == 1) { 1152 937 subsampling = 0x33; ··· 1154 941 subsampling = get_byte(&jpeg_buffer); 1155 942 skip(&jpeg_buffer, 1); 1156 943 } 1157 - 944 + if (components > 3) 945 + return false; 1158 946 skip(&jpeg_buffer, components * 2); 947 + notfound = 0; 948 + break; 949 + 950 + case DQT: 951 + if (get_word_be(&jpeg_buffer, &word)) 952 + break; 953 + length = (long)word - 2; 954 + if (!length) 955 + return false; 956 + if (n_dqt >= S5P_JPEG_MAX_MARKER) 957 + return false; 958 + dqt[n_dqt] = jpeg_buffer.curr; /* after 0xffdb */ 959 + dqt_len[n_dqt++] = length; 960 + skip(&jpeg_buffer, length); 961 + break; 962 + 963 + case DHT: 964 + if (get_word_be(&jpeg_buffer, &word)) 965 + break; 966 + length = (long)word - 2; 967 + if (!length) 968 + return false; 969 + if (n_dht >= S5P_JPEG_MAX_MARKER) 970 + return false; 971 + dht[n_dht] = jpeg_buffer.curr; /* after 0xffc4 */ 972 + dht_len[n_dht++] = length; 973 + skip(&jpeg_buffer, length); 974 + break; 975 + 976 + case SOS: 977 + sos = jpeg_buffer.curr - 2; /* 0xffda */ 1159 978 break; 1160 979 1161 980 /* skip payload-less markers */ ··· 1208 963 } 1209 964 result->w = width; 1210 965 result->h = height; 1211 - result->size = components; 966 + result->sos = sos; 967 + result->dht.n = n_dht; 968 + while (n_dht--) { 969 + result->dht.marker[n_dht] = dht[n_dht]; 970 + result->dht.len[n_dht] = dht_len[n_dht]; 971 + } 972 + result->dqt.n = n_dqt; 973 + while (n_dqt--) { 974 + result->dqt.marker[n_dqt] = dqt[n_dqt]; 975 + result->dqt.len[n_dqt] = dqt_len[n_dqt]; 976 + } 977 + result->sof = sof; 978 + result->sof_len = sof_len; 979 + result->size = result->components = components; 1212 980 1213 981 switch (subsampling) { 1214 982 case 0x11: ··· 1240 982 return false; 1241 983 } 1242 984 1243 - return !notfound; 985 + return !notfound && sos; 1244 986 } 1245 987 1246 988 static int s5p_jpeg_querycap(struct file *file, void *priv, ··· 1484 1226 return -EINVAL; 1485 1227 } 1486 1228 1487 - if ((ctx->jpeg->variant->version != SJPEG_EXYNOS4) || 1488 - (ctx->mode != S5P_JPEG_DECODE)) 1229 + if (!ctx->jpeg->variant->hw_ex4_compat || ctx->mode != S5P_JPEG_DECODE) 1489 1230 goto exit; 1490 1231 1491 1232 /* ··· 1607 1350 * the JPEG_IMAGE_SIZE register. In order to avoid sysmmu 1608 1351 * page fault calculate proper buffer size in such a case. 1609 1352 */ 1610 - if (ct->jpeg->variant->version == SJPEG_EXYNOS4 && 1353 + if (ct->jpeg->variant->hw_ex4_compat && 1611 1354 f_type == FMT_TYPE_OUTPUT && ct->mode == S5P_JPEG_ENCODE) 1612 1355 q_data->size = exynos4_jpeg_get_output_buffer_size(ct, 1613 1356 f, ··· 2146 1889 vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); 2147 1890 2148 1891 jpeg_addr = vb2_dma_contig_plane_dma_addr(vb, 0); 1892 + if (jpeg->variant->version == SJPEG_EXYNOS5433 && 1893 + ctx->mode == S5P_JPEG_DECODE) 1894 + jpeg_addr += ctx->out_q.sos; 2149 1895 exynos4_jpeg_set_stream_buf_address(jpeg->regs, jpeg_addr); 1896 + } 1897 + 1898 + static inline void exynos4_jpeg_set_img_fmt(void __iomem *base, 1899 + unsigned int img_fmt) 1900 + { 1901 + __exynos4_jpeg_set_img_fmt(base, img_fmt, SJPEG_EXYNOS4); 1902 + } 1903 + 1904 + static inline void exynos5433_jpeg_set_img_fmt(void __iomem *base, 1905 + unsigned int img_fmt) 1906 + { 1907 + __exynos4_jpeg_set_img_fmt(base, img_fmt, SJPEG_EXYNOS5433); 1908 + } 1909 + 1910 + static inline void exynos4_jpeg_set_enc_out_fmt(void __iomem *base, 1911 + unsigned int out_fmt) 1912 + { 1913 + __exynos4_jpeg_set_enc_out_fmt(base, out_fmt, SJPEG_EXYNOS4); 1914 + } 1915 + 1916 + static inline void exynos5433_jpeg_set_enc_out_fmt(void __iomem *base, 1917 + unsigned int out_fmt) 1918 + { 1919 + __exynos4_jpeg_set_enc_out_fmt(base, out_fmt, SJPEG_EXYNOS5433); 2150 1920 } 2151 1921 2152 1922 static void exynos4_jpeg_device_run(void *priv) ··· 2183 1899 unsigned int bitstream_size; 2184 1900 unsigned long flags; 2185 1901 2186 - spin_lock_irqsave(&ctx->jpeg->slock, flags); 1902 + spin_lock_irqsave(&jpeg->slock, flags); 2187 1903 2188 1904 if (ctx->mode == S5P_JPEG_ENCODE) { 2189 1905 exynos4_jpeg_sw_reset(jpeg->regs); 2190 - exynos4_jpeg_set_interrupt(jpeg->regs); 1906 + exynos4_jpeg_set_interrupt(jpeg->regs, jpeg->variant->version); 2191 1907 exynos4_jpeg_set_huf_table_enable(jpeg->regs, 1); 2192 1908 2193 1909 exynos4_jpeg_set_huff_tbl(jpeg->regs); ··· 2204 1920 exynos4_jpeg_set_stream_size(jpeg->regs, ctx->cap_q.w, 2205 1921 ctx->cap_q.h); 2206 1922 2207 - exynos4_jpeg_set_enc_out_fmt(jpeg->regs, ctx->subsampling); 2208 - exynos4_jpeg_set_img_fmt(jpeg->regs, ctx->out_q.fmt->fourcc); 1923 + if (ctx->jpeg->variant->version == SJPEG_EXYNOS4) { 1924 + exynos4_jpeg_set_enc_out_fmt(jpeg->regs, 1925 + ctx->subsampling); 1926 + exynos4_jpeg_set_img_fmt(jpeg->regs, 1927 + ctx->out_q.fmt->fourcc); 1928 + } else { 1929 + exynos5433_jpeg_set_enc_out_fmt(jpeg->regs, 1930 + ctx->subsampling); 1931 + exynos5433_jpeg_set_img_fmt(jpeg->regs, 1932 + ctx->out_q.fmt->fourcc); 1933 + } 2209 1934 exynos4_jpeg_set_img_addr(ctx); 2210 1935 exynos4_jpeg_set_jpeg_addr(ctx); 2211 1936 exynos4_jpeg_set_encode_hoff_cnt(jpeg->regs, 2212 1937 ctx->out_q.fmt->fourcc); 2213 1938 } else { 2214 1939 exynos4_jpeg_sw_reset(jpeg->regs); 2215 - exynos4_jpeg_set_interrupt(jpeg->regs); 1940 + exynos4_jpeg_set_interrupt(jpeg->regs, 1941 + jpeg->variant->version); 2216 1942 exynos4_jpeg_set_img_addr(ctx); 2217 1943 exynos4_jpeg_set_jpeg_addr(ctx); 2218 - exynos4_jpeg_set_img_fmt(jpeg->regs, ctx->cap_q.fmt->fourcc); 2219 1944 2220 - bitstream_size = DIV_ROUND_UP(ctx->out_q.size, 32); 1945 + if (jpeg->variant->version == SJPEG_EXYNOS5433) { 1946 + exynos4_jpeg_parse_huff_tbl(ctx); 1947 + exynos4_jpeg_parse_decode_h_tbl(ctx); 1948 + 1949 + exynos4_jpeg_parse_q_tbl(ctx); 1950 + exynos4_jpeg_parse_decode_q_tbl(ctx); 1951 + 1952 + exynos4_jpeg_set_huf_table_enable(jpeg->regs, 1); 1953 + 1954 + exynos4_jpeg_set_stream_size(jpeg->regs, ctx->cap_q.w, 1955 + ctx->cap_q.h); 1956 + exynos5433_jpeg_set_enc_out_fmt(jpeg->regs, 1957 + ctx->subsampling); 1958 + exynos5433_jpeg_set_img_fmt(jpeg->regs, 1959 + ctx->cap_q.fmt->fourcc); 1960 + bitstream_size = DIV_ROUND_UP(ctx->out_q.size, 16); 1961 + } else { 1962 + exynos4_jpeg_set_img_fmt(jpeg->regs, 1963 + ctx->cap_q.fmt->fourcc); 1964 + bitstream_size = DIV_ROUND_UP(ctx->out_q.size, 32); 1965 + } 2221 1966 2222 1967 exynos4_jpeg_set_dec_bitstream_size(jpeg->regs, bitstream_size); 2223 1968 } 2224 1969 2225 1970 exynos4_jpeg_set_enc_dec_mode(jpeg->regs, ctx->mode); 2226 1971 2227 - spin_unlock_irqrestore(&ctx->jpeg->slock, flags); 1972 + spin_unlock_irqrestore(&jpeg->slock, flags); 2228 1973 } 2229 1974 2230 1975 static void exynos3250_jpeg_set_img_addr(struct s5p_jpeg_ctx *ctx) ··· 2500 2187 q_data = &ctx->out_q; 2501 2188 q_data->w = tmp.w; 2502 2189 q_data->h = tmp.h; 2190 + q_data->sos = tmp.sos; 2191 + memcpy(q_data->dht.marker, tmp.dht.marker, 2192 + sizeof(tmp.dht.marker)); 2193 + memcpy(q_data->dht.len, tmp.dht.len, sizeof(tmp.dht.len)); 2194 + q_data->dht.n = tmp.dht.n; 2195 + memcpy(q_data->dqt.marker, tmp.dqt.marker, 2196 + sizeof(tmp.dqt.marker)); 2197 + memcpy(q_data->dqt.len, tmp.dqt.len, sizeof(tmp.dqt.len)); 2198 + q_data->dqt.n = tmp.dqt.n; 2199 + q_data->sof = tmp.sof; 2200 + q_data->sof_len = tmp.sof_len; 2503 2201 2504 2202 q_data = &ctx->cap_q; 2505 2203 q_data->w = tmp.w; ··· 2697 2373 } 2698 2374 2699 2375 v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx); 2700 - curr_ctx->subsampling = exynos4_jpeg_get_frame_fmt(jpeg->regs); 2376 + if (jpeg->variant->version == SJPEG_EXYNOS4) 2377 + curr_ctx->subsampling = exynos4_jpeg_get_frame_fmt(jpeg->regs); 2701 2378 2702 2379 spin_unlock(&jpeg->slock); 2703 2380 return IRQ_HANDLED; ··· 3050 2725 .htbl_reinit = 1, 3051 2726 .clk_names = {"jpeg"}, 3052 2727 .num_clocks = 1, 2728 + .hw_ex4_compat = 1, 3053 2729 }; 3054 2730 3055 2731 static struct s5p_jpeg_variant exynos5420_jpeg_drvdata = { ··· 3062 2736 .htbl_reinit = 1, 3063 2737 .clk_names = {"jpeg"}, 3064 2738 .num_clocks = 1, 2739 + }; 2740 + 2741 + static struct s5p_jpeg_variant exynos5433_jpeg_drvdata = { 2742 + .version = SJPEG_EXYNOS5433, 2743 + .jpeg_irq = exynos4_jpeg_irq, 2744 + .m2m_ops = &exynos4_jpeg_m2m_ops, 2745 + .fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS4, 2746 + .htbl_reinit = 1, 2747 + .clk_names = {"pclk", "aclk", "aclk_xiu", "sclk"}, 2748 + .num_clocks = 4, 2749 + .hw_ex4_compat = 1, 3065 2750 }; 3066 2751 3067 2752 static const struct of_device_id samsung_jpeg_match[] = { ··· 3091 2754 }, { 3092 2755 .compatible = "samsung,exynos5420-jpeg", 3093 2756 .data = &exynos5420_jpeg_drvdata, 2757 + }, { 2758 + .compatible = "samsung,exynos5433-jpeg", 2759 + .data = &exynos5433_jpeg_drvdata, 3094 2760 }, 3095 2761 {}, 3096 2762 };
+31
drivers/media/platform/s5p-jpeg/jpeg-core.h
··· 42 42 /* a selection of JPEG markers */ 43 43 #define TEM 0x01 44 44 #define SOF0 0xc0 45 + #define DHT 0xc4 45 46 #define RST 0xd0 46 47 #define SOI 0xd8 47 48 #define EOI 0xd9 49 + #define SOS 0xda 50 + #define DQT 0xdb 48 51 #define DHP 0xde 49 52 50 53 /* Flags that indicate a format can be used for capture/output */ ··· 71 68 #define SJPEG_SUBSAMPLING_422 0x21 72 69 #define SJPEG_SUBSAMPLING_420 0x22 73 70 71 + #define S5P_JPEG_MAX_MARKER 4 72 + 74 73 /* Version numbers */ 75 74 enum sjpeg_version { 76 75 SJPEG_S5P, 77 76 SJPEG_EXYNOS3250, 78 77 SJPEG_EXYNOS4, 79 78 SJPEG_EXYNOS5420, 79 + SJPEG_EXYNOS5433, 80 80 }; 81 81 82 82 enum exynos4_jpeg_result { ··· 140 134 unsigned int fmt_ver_flag; 141 135 unsigned int hw3250_compat:1; 142 136 unsigned int htbl_reinit:1; 137 + unsigned int hw_ex4_compat:1; 143 138 struct v4l2_m2m_ops *m2m_ops; 144 139 irqreturn_t (*jpeg_irq)(int irq, void *priv); 145 140 const char *clk_names[JPEG_MAX_CLOCKS]; ··· 170 163 }; 171 164 172 165 /** 166 + * s5p_jpeg_marker - collection of markers from jpeg header 167 + * @marker: markers' positions relative to the buffer beginning 168 + * @len: markers' payload lengths (without length field) 169 + * @n: number of markers in collection 170 + */ 171 + struct s5p_jpeg_marker { 172 + u32 marker[S5P_JPEG_MAX_MARKER]; 173 + u32 len[S5P_JPEG_MAX_MARKER]; 174 + u32 n; 175 + }; 176 + 177 + /** 173 178 * s5p_jpeg_q_data - parameters of one queue 174 179 * @fmt: driver-specific format of this queue 175 180 * @w: image width 176 181 * @h: image height 182 + * @sos: SOS marker's position relative to the buffer beginning 183 + * @dht: DHT markers' positions relative to the buffer beginning 184 + * @dqt: DQT markers' positions relative to the buffer beginning 185 + * @sof: SOF0 marker's postition relative to the buffer beginning 186 + * @sof_len: SOF0 marker's payload length (without length field itself) 187 + * @components: number of image components 177 188 * @size: image buffer size in bytes 178 189 */ 179 190 struct s5p_jpeg_q_data { 180 191 struct s5p_jpeg_fmt *fmt; 181 192 u32 w; 182 193 u32 h; 194 + u32 sos; 195 + struct s5p_jpeg_marker dht; 196 + struct s5p_jpeg_marker dqt; 197 + u32 sof; 198 + u32 sof_len; 199 + u32 components; 183 200 u32 size; 184 201 }; 185 202
+66 -14
drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c
··· 45 45 } 46 46 } 47 47 48 - void exynos4_jpeg_set_img_fmt(void __iomem *base, unsigned int img_fmt) 48 + void __exynos4_jpeg_set_img_fmt(void __iomem *base, unsigned int img_fmt, 49 + unsigned int version) 49 50 { 50 51 unsigned int reg; 52 + unsigned int exynos4_swap_chroma_cbcr; 53 + unsigned int exynos4_swap_chroma_crcb; 54 + 55 + if (version == SJPEG_EXYNOS4) { 56 + exynos4_swap_chroma_cbcr = EXYNOS4_SWAP_CHROMA_CBCR; 57 + exynos4_swap_chroma_crcb = EXYNOS4_SWAP_CHROMA_CRCB; 58 + } else { 59 + exynos4_swap_chroma_cbcr = EXYNOS5433_SWAP_CHROMA_CBCR; 60 + exynos4_swap_chroma_crcb = EXYNOS5433_SWAP_CHROMA_CRCB; 61 + } 51 62 52 63 reg = readl(base + EXYNOS4_IMG_FMT_REG) & 53 64 EXYNOS4_ENC_IN_FMT_MASK; /* clear except enc format */ ··· 78 67 case V4L2_PIX_FMT_NV24: 79 68 reg = reg | EXYNOS4_ENC_YUV_444_IMG | 80 69 EXYNOS4_YUV_444_IP_YUV_444_2P_IMG | 81 - EXYNOS4_SWAP_CHROMA_CBCR; 70 + exynos4_swap_chroma_cbcr; 82 71 break; 83 72 case V4L2_PIX_FMT_NV42: 84 73 reg = reg | EXYNOS4_ENC_YUV_444_IMG | 85 74 EXYNOS4_YUV_444_IP_YUV_444_2P_IMG | 86 - EXYNOS4_SWAP_CHROMA_CRCB; 75 + exynos4_swap_chroma_crcb; 87 76 break; 88 77 case V4L2_PIX_FMT_YUYV: 89 78 reg = reg | EXYNOS4_DEC_YUV_422_IMG | 90 79 EXYNOS4_YUV_422_IP_YUV_422_1P_IMG | 91 - EXYNOS4_SWAP_CHROMA_CBCR; 80 + exynos4_swap_chroma_cbcr; 92 81 break; 93 82 94 83 case V4L2_PIX_FMT_YVYU: 95 84 reg = reg | EXYNOS4_DEC_YUV_422_IMG | 96 85 EXYNOS4_YUV_422_IP_YUV_422_1P_IMG | 97 - EXYNOS4_SWAP_CHROMA_CRCB; 86 + exynos4_swap_chroma_crcb; 98 87 break; 99 88 case V4L2_PIX_FMT_NV16: 100 89 reg = reg | EXYNOS4_DEC_YUV_422_IMG | 101 90 EXYNOS4_YUV_422_IP_YUV_422_2P_IMG | 102 - EXYNOS4_SWAP_CHROMA_CBCR; 91 + exynos4_swap_chroma_cbcr; 103 92 break; 104 93 case V4L2_PIX_FMT_NV61: 105 94 reg = reg | EXYNOS4_DEC_YUV_422_IMG | 106 95 EXYNOS4_YUV_422_IP_YUV_422_2P_IMG | 107 - EXYNOS4_SWAP_CHROMA_CRCB; 96 + exynos4_swap_chroma_crcb; 108 97 break; 109 98 case V4L2_PIX_FMT_NV12: 110 99 reg = reg | EXYNOS4_DEC_YUV_420_IMG | 111 100 EXYNOS4_YUV_420_IP_YUV_420_2P_IMG | 112 - EXYNOS4_SWAP_CHROMA_CBCR; 101 + exynos4_swap_chroma_cbcr; 113 102 break; 114 103 case V4L2_PIX_FMT_NV21: 115 104 reg = reg | EXYNOS4_DEC_YUV_420_IMG | 116 105 EXYNOS4_YUV_420_IP_YUV_420_2P_IMG | 117 - EXYNOS4_SWAP_CHROMA_CRCB; 106 + exynos4_swap_chroma_crcb; 118 107 break; 119 108 case V4L2_PIX_FMT_YUV420: 120 109 reg = reg | EXYNOS4_DEC_YUV_420_IMG | 121 110 EXYNOS4_YUV_420_IP_YUV_420_3P_IMG | 122 - EXYNOS4_SWAP_CHROMA_CBCR; 111 + exynos4_swap_chroma_cbcr; 123 112 break; 124 113 default: 125 114 break; ··· 129 118 writel(reg, base + EXYNOS4_IMG_FMT_REG); 130 119 } 131 120 132 - void exynos4_jpeg_set_enc_out_fmt(void __iomem *base, unsigned int out_fmt) 121 + void __exynos4_jpeg_set_enc_out_fmt(void __iomem *base, unsigned int out_fmt, 122 + unsigned int version) 133 123 { 134 124 unsigned int reg; 135 125 136 126 reg = readl(base + EXYNOS4_IMG_FMT_REG) & 137 - ~EXYNOS4_ENC_FMT_MASK; /* clear enc format */ 127 + ~(version == SJPEG_EXYNOS4 ? EXYNOS4_ENC_FMT_MASK : 128 + EXYNOS5433_ENC_FMT_MASK); /* clear enc format */ 138 129 139 130 switch (out_fmt) { 140 131 case V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY: ··· 162 149 writel(reg, base + EXYNOS4_IMG_FMT_REG); 163 150 } 164 151 165 - void exynos4_jpeg_set_interrupt(void __iomem *base) 152 + void exynos4_jpeg_set_interrupt(void __iomem *base, unsigned int version) 166 153 { 167 - writel(EXYNOS4_INT_EN_ALL, base + EXYNOS4_INT_EN_REG); 154 + unsigned int reg; 155 + 156 + if (version == SJPEG_EXYNOS4) { 157 + reg = readl(base + EXYNOS4_INT_EN_REG) & ~EXYNOS4_INT_EN_MASK; 158 + writel(reg | EXYNOS4_INT_EN_ALL, base + EXYNOS4_INT_EN_REG); 159 + } else { 160 + reg = readl(base + EXYNOS4_INT_EN_REG) & 161 + ~EXYNOS5433_INT_EN_MASK; 162 + writel(reg | EXYNOS5433_INT_EN_ALL, base + EXYNOS4_INT_EN_REG); 163 + } 168 164 } 169 165 170 166 unsigned int exynos4_jpeg_get_int_status(void __iomem *base) ··· 253 231 EXYNOS4_HUFF_TBL_COMP2_AC_0_DC_0 | 254 232 EXYNOS4_HUFF_TBL_COMP3_AC_1_DC_1; 255 233 234 + writel(reg, base + EXYNOS4_TBL_SEL_REG); 235 + } 236 + 237 + void exynos4_jpeg_set_dec_components(void __iomem *base, int n) 238 + { 239 + unsigned int reg; 240 + 241 + reg = readl(base + EXYNOS4_TBL_SEL_REG); 242 + 243 + reg |= EXYNOS4_NF(n); 244 + writel(reg, base + EXYNOS4_TBL_SEL_REG); 245 + } 246 + 247 + void exynos4_jpeg_select_dec_q_tbl(void __iomem *base, char c, char x) 248 + { 249 + unsigned int reg; 250 + 251 + reg = readl(base + EXYNOS4_TBL_SEL_REG); 252 + 253 + reg |= EXYNOS4_Q_TBL_COMP(c, x); 254 + writel(reg, base + EXYNOS4_TBL_SEL_REG); 255 + } 256 + 257 + void exynos4_jpeg_select_dec_h_tbl(void __iomem *base, char c, char x) 258 + { 259 + unsigned int reg; 260 + 261 + reg = readl(base + EXYNOS4_TBL_SEL_REG); 262 + 263 + reg |= EXYNOS4_HUFF_TBL_COMP(c, x); 256 264 writel(reg, base + EXYNOS4_TBL_SEL_REG); 257 265 } 258 266
+8 -3
drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.h
··· 15 15 16 16 void exynos4_jpeg_sw_reset(void __iomem *base); 17 17 void exynos4_jpeg_set_enc_dec_mode(void __iomem *base, unsigned int mode); 18 - void exynos4_jpeg_set_img_fmt(void __iomem *base, unsigned int img_fmt); 19 - void exynos4_jpeg_set_enc_out_fmt(void __iomem *base, unsigned int out_fmt); 18 + void __exynos4_jpeg_set_img_fmt(void __iomem *base, unsigned int img_fmt, 19 + unsigned int version); 20 + void __exynos4_jpeg_set_enc_out_fmt(void __iomem *base, unsigned int out_fmt, 21 + unsigned int version); 20 22 void exynos4_jpeg_set_enc_tbl(void __iomem *base); 21 - void exynos4_jpeg_set_interrupt(void __iomem *base); 23 + void exynos4_jpeg_set_interrupt(void __iomem *base, unsigned int version); 22 24 unsigned int exynos4_jpeg_get_int_status(void __iomem *base); 23 25 void exynos4_jpeg_set_huf_table_enable(void __iomem *base, int value); 24 26 void exynos4_jpeg_set_sys_int_enable(void __iomem *base, int value); ··· 32 30 struct s5p_jpeg_addr *jpeg_addr); 33 31 void exynos4_jpeg_set_encode_tbl_select(void __iomem *base, 34 32 enum exynos4_jpeg_img_quality_level level); 33 + void exynos4_jpeg_set_dec_components(void __iomem *base, int n); 34 + void exynos4_jpeg_select_dec_q_tbl(void __iomem *base, char c, char x); 35 + void exynos4_jpeg_select_dec_h_tbl(void __iomem *base, char c, char x); 35 36 void exynos4_jpeg_set_encode_hoff_cnt(void __iomem *base, unsigned int fmt); 36 37 void exynos4_jpeg_set_dec_bitstream_size(void __iomem *base, unsigned int size); 37 38 unsigned int exynos4_jpeg_get_stream_size(void __iomem *base);
+51 -24
drivers/media/platform/s5p-jpeg/jpeg-regs.h
··· 231 231 232 232 /* JPEG INT Register bit */ 233 233 #define EXYNOS4_INT_EN_MASK (0x1f << 0) 234 + #define EXYNOS5433_INT_EN_MASK (0x1ff << 0) 234 235 #define EXYNOS4_PROT_ERR_INT_EN (1 << 0) 235 236 #define EXYNOS4_IMG_COMPLETION_INT_EN (1 << 1) 236 237 #define EXYNOS4_DEC_INVALID_FORMAT_EN (1 << 2) 237 238 #define EXYNOS4_MULTI_SCAN_ERROR_EN (1 << 3) 238 239 #define EXYNOS4_FRAME_ERR_EN (1 << 4) 239 240 #define EXYNOS4_INT_EN_ALL (0x1f << 0) 241 + #define EXYNOS5433_INT_EN_ALL (0x1b6 << 0) 240 242 241 243 #define EXYNOS4_MOD_REG_PROC_ENC (0 << 3) 242 244 #define EXYNOS4_MOD_REG_PROC_DEC (1 << 3) ··· 298 296 299 297 #define EXYNOS4_ENC_FMT_SHIFT 24 300 298 #define EXYNOS4_ENC_FMT_MASK (3 << EXYNOS4_ENC_FMT_SHIFT) 299 + #define EXYNOS5433_ENC_FMT_MASK (7 << EXYNOS4_ENC_FMT_SHIFT) 300 + 301 301 #define EXYNOS4_ENC_FMT_GRAY (0 << EXYNOS4_ENC_FMT_SHIFT) 302 302 #define EXYNOS4_ENC_FMT_YUV_444 (1 << EXYNOS4_ENC_FMT_SHIFT) 303 303 #define EXYNOS4_ENC_FMT_YUV_422 (2 << EXYNOS4_ENC_FMT_SHIFT) ··· 309 305 310 306 #define EXYNOS4_SWAP_CHROMA_CRCB (1 << 26) 311 307 #define EXYNOS4_SWAP_CHROMA_CBCR (0 << 26) 308 + #define EXYNOS5433_SWAP_CHROMA_CRCB (1 << 27) 309 + #define EXYNOS5433_SWAP_CHROMA_CBCR (0 << 27) 312 310 313 311 /* JPEG HUFF count Register bit */ 314 312 #define EXYNOS4_HUFF_COUNT_MASK 0xffff ··· 322 316 #define EXYNOS4_DECODED_IMG_FMT_MASK 0x3 323 317 324 318 /* JPEG TBL SEL Register bit */ 325 - #define EXYNOS4_Q_TBL_COMP1_0 (0 << 0) 326 - #define EXYNOS4_Q_TBL_COMP1_1 (1 << 0) 327 - #define EXYNOS4_Q_TBL_COMP1_2 (2 << 0) 328 - #define EXYNOS4_Q_TBL_COMP1_3 (3 << 0) 319 + #define EXYNOS4_Q_TBL_COMP(c, n) ((n) << (((c) - 1) << 1)) 329 320 330 - #define EXYNOS4_Q_TBL_COMP2_0 (0 << 2) 331 - #define EXYNOS4_Q_TBL_COMP2_1 (1 << 2) 332 - #define EXYNOS4_Q_TBL_COMP2_2 (2 << 2) 333 - #define EXYNOS4_Q_TBL_COMP2_3 (3 << 2) 321 + #define EXYNOS4_Q_TBL_COMP1_0 EXYNOS4_Q_TBL_COMP(1, 0) 322 + #define EXYNOS4_Q_TBL_COMP1_1 EXYNOS4_Q_TBL_COMP(1, 1) 323 + #define EXYNOS4_Q_TBL_COMP1_2 EXYNOS4_Q_TBL_COMP(1, 2) 324 + #define EXYNOS4_Q_TBL_COMP1_3 EXYNOS4_Q_TBL_COMP(1, 3) 334 325 335 - #define EXYNOS4_Q_TBL_COMP3_0 (0 << 4) 336 - #define EXYNOS4_Q_TBL_COMP3_1 (1 << 4) 337 - #define EXYNOS4_Q_TBL_COMP3_2 (2 << 4) 338 - #define EXYNOS4_Q_TBL_COMP3_3 (3 << 4) 326 + #define EXYNOS4_Q_TBL_COMP2_0 EXYNOS4_Q_TBL_COMP(2, 0) 327 + #define EXYNOS4_Q_TBL_COMP2_1 EXYNOS4_Q_TBL_COMP(2, 1) 328 + #define EXYNOS4_Q_TBL_COMP2_2 EXYNOS4_Q_TBL_COMP(2, 2) 329 + #define EXYNOS4_Q_TBL_COMP2_3 EXYNOS4_Q_TBL_COMP(2, 3) 339 330 340 - #define EXYNOS4_HUFF_TBL_COMP1_AC_0_DC_0 (0 << 6) 341 - #define EXYNOS4_HUFF_TBL_COMP1_AC_0_DC_1 (1 << 6) 342 - #define EXYNOS4_HUFF_TBL_COMP1_AC_1_DC_0 (2 << 6) 343 - #define EXYNOS4_HUFF_TBL_COMP1_AC_1_DC_1 (3 << 6) 331 + #define EXYNOS4_Q_TBL_COMP3_0 EXYNOS4_Q_TBL_COMP(3, 0) 332 + #define EXYNOS4_Q_TBL_COMP3_1 EXYNOS4_Q_TBL_COMP(3, 1) 333 + #define EXYNOS4_Q_TBL_COMP3_2 EXYNOS4_Q_TBL_COMP(3, 2) 334 + #define EXYNOS4_Q_TBL_COMP3_3 EXYNOS4_Q_TBL_COMP(3, 3) 344 335 345 - #define EXYNOS4_HUFF_TBL_COMP2_AC_0_DC_0 (0 << 8) 346 - #define EXYNOS4_HUFF_TBL_COMP2_AC_0_DC_1 (1 << 8) 347 - #define EXYNOS4_HUFF_TBL_COMP2_AC_1_DC_0 (2 << 8) 348 - #define EXYNOS4_HUFF_TBL_COMP2_AC_1_DC_1 (3 << 8) 336 + #define EXYNOS4_HUFF_TBL_COMP(c, n) ((n) << ((((c) - 1) << 1) + 6)) 349 337 350 - #define EXYNOS4_HUFF_TBL_COMP3_AC_0_DC_0 (0 << 10) 351 - #define EXYNOS4_HUFF_TBL_COMP3_AC_0_DC_1 (1 << 10) 352 - #define EXYNOS4_HUFF_TBL_COMP3_AC_1_DC_0 (2 << 10) 353 - #define EXYNOS4_HUFF_TBL_COMP3_AC_1_DC_1 (3 << 10) 338 + #define EXYNOS4_HUFF_TBL_COMP1_AC_0_DC_0 \ 339 + EXYNOS4_HUFF_TBL_COMP(1, 0) 340 + #define EXYNOS4_HUFF_TBL_COMP1_AC_0_DC_1 \ 341 + EXYNOS4_HUFF_TBL_COMP(1, 1) 342 + #define EXYNOS4_HUFF_TBL_COMP1_AC_1_DC_0 \ 343 + EXYNOS4_HUFF_TBL_COMP(1, 2) 344 + #define EXYNOS4_HUFF_TBL_COMP1_AC_1_DC_1 \ 345 + EXYNOS4_HUFF_TBL_COMP(1, 3) 346 + 347 + #define EXYNOS4_HUFF_TBL_COMP2_AC_0_DC_0 \ 348 + EXYNOS4_HUFF_TBL_COMP(2, 0) 349 + #define EXYNOS4_HUFF_TBL_COMP2_AC_0_DC_1 \ 350 + EXYNOS4_HUFF_TBL_COMP(2, 1) 351 + #define EXYNOS4_HUFF_TBL_COMP2_AC_1_DC_0 \ 352 + EXYNOS4_HUFF_TBL_COMP(2, 2) 353 + #define EXYNOS4_HUFF_TBL_COMP2_AC_1_DC_1 \ 354 + EXYNOS4_HUFF_TBL_COMP(2, 3) 355 + 356 + #define EXYNOS4_HUFF_TBL_COMP3_AC_0_DC_0 \ 357 + EXYNOS4_HUFF_TBL_COMP(3, 0) 358 + #define EXYNOS4_HUFF_TBL_COMP3_AC_0_DC_1 \ 359 + EXYNOS4_HUFF_TBL_COMP(3, 1) 360 + #define EXYNOS4_HUFF_TBL_COMP3_AC_1_DC_0 \ 361 + EXYNOS4_HUFF_TBL_COMP(3, 2) 362 + #define EXYNOS4_HUFF_TBL_COMP3_AC_1_DC_1 \ 363 + EXYNOS4_HUFF_TBL_COMP(3, 3) 364 + 365 + #define EXYNOS4_NF_SHIFT 16 366 + #define EXYNOS4_NF_MASK 0xff 367 + #define EXYNOS4_NF(x) \ 368 + (((x) << EXYNOS4_NF_SHIFT) & EXYNOS4_NF_MASK) 354 369 355 370 /* JPEG quantizer table register */ 356 371 #define EXYNOS4_QTBL_CONTENT(n) (0x100 + (n) * 0x40)