1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * TW5864 driver - video encoding functions 4 * 5 * Copyright (C) 2016 Bluecherry, LLC <maintainers@bluecherrydvr.com> 6 */ 7 8 #include <linux/module.h> 9 #include <media/v4l2-common.h> 10 #include <media/v4l2-event.h> 11 #include <media/videobuf2-dma-contig.h> 12 13 #include "tw5864.h" 14 #include "tw5864-reg.h" 15 16 #define QUANTIZATION_TABLE_LEN 96 17 #define VLC_LOOKUP_TABLE_LEN 1024 18 19 static const u16 forward_quantization_table[QUANTIZATION_TABLE_LEN] = { 20 0x3333, 0x1f82, 0x3333, 0x1f82, 0x1f82, 0x147b, 0x1f82, 0x147b, 21 0x3333, 0x1f82, 0x3333, 0x1f82, 0x1f82, 0x147b, 0x1f82, 0x147b, 22 0x2e8c, 0x1d42, 0x2e8c, 0x1d42, 0x1d42, 0x1234, 0x1d42, 0x1234, 23 0x2e8c, 0x1d42, 0x2e8c, 0x1d42, 0x1d42, 0x1234, 0x1d42, 0x1234, 24 0x2762, 0x199a, 0x2762, 0x199a, 0x199a, 0x1062, 0x199a, 0x1062, 25 0x2762, 0x199a, 0x2762, 0x199a, 0x199a, 0x1062, 0x199a, 0x1062, 26 0x2492, 0x16c1, 0x2492, 0x16c1, 0x16c1, 0x0e3f, 0x16c1, 0x0e3f, 27 0x2492, 0x16c1, 0x2492, 0x16c1, 0x16c1, 0x0e3f, 0x16c1, 0x0e3f, 28 0x2000, 0x147b, 0x2000, 0x147b, 0x147b, 0x0d1b, 0x147b, 0x0d1b, 29 0x2000, 0x147b, 0x2000, 0x147b, 0x147b, 0x0d1b, 0x147b, 0x0d1b, 30 0x1c72, 0x11cf, 0x1c72, 0x11cf, 0x11cf, 0x0b4d, 0x11cf, 0x0b4d, 31 0x1c72, 0x11cf, 0x1c72, 0x11cf, 0x11cf, 0x0b4d, 0x11cf, 0x0b4d 32 }; 33 34 static const u16 inverse_quantization_table[QUANTIZATION_TABLE_LEN] = { 35 0x800a, 0x800d, 0x800a, 0x800d, 0x800d, 0x8010, 0x800d, 0x8010, 36 0x800a, 0x800d, 0x800a, 0x800d, 0x800d, 0x8010, 0x800d, 0x8010, 37 0x800b, 0x800e, 0x800b, 0x800e, 0x800e, 0x8012, 0x800e, 0x8012, 38 0x800b, 0x800e, 0x800b, 0x800e, 0x800e, 0x8012, 0x800e, 0x8012, 39 0x800d, 0x8010, 0x800d, 0x8010, 0x8010, 0x8014, 0x8010, 0x8014, 40 0x800d, 0x8010, 0x800d, 0x8010, 0x8010, 0x8014, 0x8010, 0x8014, 41 0x800e, 0x8012, 0x800e, 0x8012, 0x8012, 0x8017, 0x8012, 0x8017, 42 0x800e, 0x8012, 0x800e, 0x8012, 0x8012, 0x8017, 0x8012, 0x8017, 43 0x8010, 0x8014, 0x8010, 0x8014, 0x8014, 0x8019, 0x8014, 0x8019, 44 0x8010, 0x8014, 0x8010, 0x8014, 0x8014, 0x8019, 0x8014, 0x8019, 45 0x8012, 0x8017, 0x8012, 0x8017, 0x8017, 0x801d, 0x8017, 0x801d, 46 0x8012, 0x8017, 0x8012, 0x8017, 0x8017, 0x801d, 0x8017, 0x801d 47 }; 48 49 static const u16 encoder_vlc_lookup_table[VLC_LOOKUP_TABLE_LEN] = { 50 0x011, 0x000, 0x000, 0x000, 0x065, 0x021, 0x000, 0x000, 0x087, 0x064, 51 0x031, 0x000, 0x097, 0x086, 0x075, 0x053, 0x0a7, 0x096, 0x085, 0x063, 52 0x0b7, 0x0a6, 0x095, 0x074, 0x0df, 0x0b6, 0x0a5, 0x084, 0x0db, 0x0de, 53 0x0b5, 0x094, 0x0d8, 0x0da, 0x0dd, 0x0a4, 0x0ef, 0x0ee, 0x0d9, 0x0b4, 54 0x0eb, 0x0ea, 0x0ed, 0x0dc, 0x0ff, 0x0fe, 0x0e9, 0x0ec, 0x0fb, 0x0fa, 55 0x0fd, 0x0e8, 0x10f, 0x0f1, 0x0f9, 0x0fc, 0x10b, 0x10e, 0x10d, 0x0f8, 56 0x107, 0x10a, 0x109, 0x10c, 0x104, 0x106, 0x105, 0x108, 0x023, 0x000, 57 0x000, 0x000, 0x06b, 0x022, 0x000, 0x000, 0x067, 0x057, 0x033, 0x000, 58 0x077, 0x06a, 0x069, 0x045, 0x087, 0x066, 0x065, 0x044, 0x084, 0x076, 59 0x075, 0x056, 0x097, 0x086, 0x085, 0x068, 0x0bf, 0x096, 0x095, 0x064, 60 0x0bb, 0x0be, 0x0bd, 0x074, 0x0cf, 0x0ba, 0x0b9, 0x094, 0x0cb, 0x0ce, 61 0x0cd, 0x0bc, 0x0c8, 0x0ca, 0x0c9, 0x0b8, 0x0df, 0x0de, 0x0dd, 0x0cc, 62 0x0db, 0x0da, 0x0d9, 0x0dc, 0x0d7, 0x0eb, 0x0d6, 0x0d8, 0x0e9, 0x0e8, 63 0x0ea, 0x0d1, 0x0e7, 0x0e6, 0x0e5, 0x0e4, 0x04f, 0x000, 0x000, 0x000, 64 0x06f, 0x04e, 0x000, 0x000, 0x06b, 0x05f, 0x04d, 0x000, 0x068, 0x05c, 65 0x05e, 0x04c, 0x07f, 0x05a, 0x05b, 0x04b, 0x07b, 0x058, 0x059, 0x04a, 66 0x079, 0x06e, 0x06d, 0x049, 0x078, 0x06a, 0x069, 0x048, 0x08f, 0x07e, 67 0x07d, 0x05d, 0x08b, 0x08e, 0x07a, 0x06c, 0x09f, 0x08a, 0x08d, 0x07c, 68 0x09b, 0x09e, 0x089, 0x08c, 0x098, 0x09a, 0x09d, 0x088, 0x0ad, 0x097, 69 0x099, 0x09c, 0x0a9, 0x0ac, 0x0ab, 0x0aa, 0x0a5, 0x0a8, 0x0a7, 0x0a6, 70 0x0a1, 0x0a4, 0x0a3, 0x0a2, 0x021, 0x000, 0x000, 0x000, 0x067, 0x011, 71 0x000, 0x000, 0x064, 0x066, 0x031, 0x000, 0x063, 0x073, 0x072, 0x065, 72 0x062, 0x083, 0x082, 0x070, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 73 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 74 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 75 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 76 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 77 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 78 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 79 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 80 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 81 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 82 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 83 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 84 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 85 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 86 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 87 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 88 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 89 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 90 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 91 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 92 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 93 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 94 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 95 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 96 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 97 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 98 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 99 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 100 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 101 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 102 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x011, 0x010, 103 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 104 0x000, 0x000, 0x000, 0x000, 0x011, 0x021, 0x020, 0x000, 0x000, 0x000, 105 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 106 0x023, 0x022, 0x021, 0x020, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 107 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x023, 0x022, 0x021, 0x031, 108 0x030, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 109 0x000, 0x000, 0x023, 0x022, 0x033, 0x032, 0x031, 0x030, 0x000, 0x000, 110 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x023, 0x030, 111 0x031, 0x033, 0x032, 0x035, 0x034, 0x000, 0x000, 0x000, 0x000, 0x000, 112 0x000, 0x000, 0x000, 0x000, 0x037, 0x036, 0x035, 0x034, 0x033, 0x032, 113 0x031, 0x041, 0x051, 0x061, 0x071, 0x081, 0x091, 0x0a1, 0x0b1, 0x000, 114 0x002, 0x000, 0x0e4, 0x011, 0x0f4, 0x002, 0x024, 0x003, 0x005, 0x012, 115 0x034, 0x013, 0x065, 0x024, 0x013, 0x063, 0x015, 0x022, 0x075, 0x034, 116 0x044, 0x023, 0x023, 0x073, 0x054, 0x033, 0x033, 0x004, 0x043, 0x014, 117 0x011, 0x043, 0x014, 0x001, 0x025, 0x015, 0x035, 0x025, 0x064, 0x055, 118 0x045, 0x035, 0x074, 0x065, 0x085, 0x0d5, 0x012, 0x095, 0x055, 0x045, 119 0x095, 0x0e5, 0x084, 0x075, 0x022, 0x0a5, 0x094, 0x085, 0x032, 0x0b5, 120 0x003, 0x0c5, 0x001, 0x044, 0x0a5, 0x032, 0x0b5, 0x094, 0x0c5, 0x0a4, 121 0x0a4, 0x054, 0x0d5, 0x0b4, 0x0b4, 0x064, 0x0f5, 0x0f5, 0x053, 0x0d4, 122 0x0e5, 0x0c4, 0x105, 0x105, 0x0c4, 0x074, 0x063, 0x0e4, 0x0d4, 0x084, 123 0x073, 0x0f4, 0x004, 0x005, 0x000, 0x053, 0x000, 0x000, 0x000, 0x000, 124 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 125 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 126 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 127 0x000, 0x000, 0x011, 0x021, 0x031, 0x030, 0x011, 0x021, 0x020, 0x000, 128 0x011, 0x010, 0x000, 0x000, 0x011, 0x033, 0x032, 0x043, 0x042, 0x053, 129 0x052, 0x063, 0x062, 0x073, 0x072, 0x083, 0x082, 0x093, 0x092, 0x091, 130 0x037, 0x036, 0x035, 0x034, 0x033, 0x045, 0x044, 0x043, 0x042, 0x053, 131 0x052, 0x063, 0x062, 0x061, 0x060, 0x000, 0x045, 0x037, 0x036, 0x035, 132 0x044, 0x043, 0x034, 0x033, 0x042, 0x053, 0x052, 0x061, 0x051, 0x060, 133 0x000, 0x000, 0x053, 0x037, 0x045, 0x044, 0x036, 0x035, 0x034, 0x043, 134 0x033, 0x042, 0x052, 0x051, 0x050, 0x000, 0x000, 0x000, 0x045, 0x044, 135 0x043, 0x037, 0x036, 0x035, 0x034, 0x033, 0x042, 0x051, 0x041, 0x050, 136 0x000, 0x000, 0x000, 0x000, 0x061, 0x051, 0x037, 0x036, 0x035, 0x034, 137 0x033, 0x032, 0x041, 0x031, 0x060, 0x000, 0x000, 0x000, 0x000, 0x000, 138 0x061, 0x051, 0x035, 0x034, 0x033, 0x023, 0x032, 0x041, 0x031, 0x060, 139 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x061, 0x041, 0x051, 0x033, 140 0x023, 0x022, 0x032, 0x031, 0x060, 0x000, 0x000, 0x000, 0x000, 0x000, 141 0x000, 0x000, 0x061, 0x060, 0x041, 0x023, 0x022, 0x031, 0x021, 0x051, 142 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x051, 0x050, 143 0x031, 0x023, 0x022, 0x021, 0x041, 0x000, 0x000, 0x000, 0x000, 0x000, 144 0x000, 0x000, 0x000, 0x000, 0x040, 0x041, 0x031, 0x032, 0x011, 0x033, 145 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 146 0x040, 0x041, 0x021, 0x011, 0x031, 0x000, 0x000, 0x000, 0x000, 0x000, 147 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x030, 0x031, 0x011, 0x021, 148 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 149 0x000, 0x000, 0x020, 0x021, 0x011, 0x000, 0x000, 0x000, 0x000, 0x000, 150 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x010, 0x011, 151 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 152 0x000, 0x000, 0x000, 0x000 153 }; 154 155 static const unsigned int lambda_lookup_table[] = { 156 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 157 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 158 0x0040, 0x0040, 0x0040, 0x0040, 0x0060, 0x0060, 0x0060, 0x0080, 159 0x0080, 0x0080, 0x00a0, 0x00c0, 0x00c0, 0x00e0, 0x0100, 0x0120, 160 0x0140, 0x0160, 0x01a0, 0x01c0, 0x0200, 0x0240, 0x0280, 0x02e0, 161 0x0320, 0x03a0, 0x0400, 0x0480, 0x0500, 0x05a0, 0x0660, 0x0720, 162 0x0800, 0x0900, 0x0a20, 0x0b60 163 }; 164 165 static const unsigned int intra4x4_lambda3[] = { 166 1, 1, 1, 1, 1, 1, 1, 1, 167 1, 1, 1, 1, 1, 1, 1, 1, 168 2, 2, 2, 2, 3, 3, 3, 4, 169 4, 4, 5, 6, 6, 7, 8, 9, 170 10, 11, 13, 14, 16, 18, 20, 23, 171 25, 29, 32, 36, 40, 45, 51, 57, 172 64, 72, 81, 91 173 }; 174 175 static v4l2_std_id tw5864_get_v4l2_std(enum tw5864_vid_std std); 176 static enum tw5864_vid_std tw5864_from_v4l2_std(v4l2_std_id v4l2_std); 177 178 static void tw5864_handle_frame_task(struct tasklet_struct *t); 179 static void tw5864_handle_frame(struct tw5864_h264_frame *frame); 180 static void tw5864_frame_interval_set(struct tw5864_input *input); 181 182 static int tw5864_queue_setup(struct vb2_queue *q, unsigned int *num_buffers, 183 unsigned int *num_planes, unsigned int sizes[], 184 struct device *alloc_ctxs[]) 185 { 186 if (*num_planes) 187 return sizes[0] < H264_VLC_BUF_SIZE ? -EINVAL : 0; 188 189 sizes[0] = H264_VLC_BUF_SIZE; 190 *num_planes = 1; 191 192 return 0; 193 } 194 195 static void tw5864_buf_queue(struct vb2_buffer *vb) 196 { 197 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 198 struct vb2_queue *vq = vb->vb2_queue; 199 struct tw5864_input *dev = vb2_get_drv_priv(vq); 200 struct tw5864_buf *buf = container_of(vbuf, struct tw5864_buf, vb); 201 unsigned long flags; 202 203 spin_lock_irqsave(&dev->slock, flags); 204 list_add_tail(&buf->list, &dev->active); 205 spin_unlock_irqrestore(&dev->slock, flags); 206 } 207 208 static int tw5864_input_std_get(struct tw5864_input *input, 209 enum tw5864_vid_std *std) 210 { 211 struct tw5864_dev *dev = input->root; 212 u8 std_reg = tw_indir_readb(TW5864_INDIR_VIN_E(input->nr)); 213 214 *std = (std_reg & 0x70) >> 4; 215 216 if (std_reg & 0x80) { 217 dev_dbg(&dev->pci->dev, 218 "Video format detection is in progress, please wait\n"); 219 return -EAGAIN; 220 } 221 222 return 0; 223 } 224 225 static int tw5864_enable_input(struct tw5864_input *input) 226 { 227 struct tw5864_dev *dev = input->root; 228 int nr = input->nr; 229 unsigned long flags; 230 int d1_width = 720; 231 int d1_height; 232 int frame_width_bus_value = 0; 233 int frame_height_bus_value = 0; 234 int reg_frame_bus = 0x1c; 235 int fmt_reg_value = 0; 236 int downscale_enabled = 0; 237 238 dev_dbg(&dev->pci->dev, "Enabling channel %d\n", nr); 239 240 input->frame_seqno = 0; 241 input->frame_gop_seqno = 0; 242 input->h264_idr_pic_id = 0; 243 244 input->reg_dsp_qp = input->qp; 245 input->reg_dsp_ref_mvp_lambda = lambda_lookup_table[input->qp]; 246 input->reg_dsp_i4x4_weight = intra4x4_lambda3[input->qp]; 247 input->reg_emu = TW5864_EMU_EN_LPF | TW5864_EMU_EN_BHOST 248 | TW5864_EMU_EN_SEN | TW5864_EMU_EN_ME | TW5864_EMU_EN_DDR; 249 input->reg_dsp = nr /* channel id */ 250 | TW5864_DSP_CHROM_SW 251 | ((0xa << 8) & TW5864_DSP_MB_DELAY) 252 ; 253 254 input->resolution = D1; 255 256 d1_height = (input->std == STD_NTSC) ? 480 : 576; 257 258 input->width = d1_width; 259 input->height = d1_height; 260 261 input->reg_interlacing = 0x4; 262 263 switch (input->resolution) { 264 case D1: 265 frame_width_bus_value = 0x2cf; 266 frame_height_bus_value = input->height - 1; 267 reg_frame_bus = 0x1c; 268 fmt_reg_value = 0; 269 downscale_enabled = 0; 270 input->reg_dsp_codec |= TW5864_CIF_MAP_MD | TW5864_HD1_MAP_MD; 271 input->reg_emu |= TW5864_DSP_FRAME_TYPE_D1; 272 input->reg_interlacing = TW5864_DI_EN | TW5864_DSP_INTER_ST; 273 274 tw_setl(TW5864_FULL_HALF_FLAG, 1 << nr); 275 break; 276 case HD1: 277 input->height /= 2; 278 input->width /= 2; 279 frame_width_bus_value = 0x2cf; 280 frame_height_bus_value = input->height * 2 - 1; 281 reg_frame_bus = 0x1c; 282 fmt_reg_value = 0; 283 downscale_enabled = 0; 284 input->reg_dsp_codec |= TW5864_HD1_MAP_MD; 285 input->reg_emu |= TW5864_DSP_FRAME_TYPE_D1; 286 287 tw_clearl(TW5864_FULL_HALF_FLAG, 1 << nr); 288 289 break; 290 case CIF: 291 input->height /= 4; 292 input->width /= 2; 293 frame_width_bus_value = 0x15f; 294 frame_height_bus_value = input->height * 2 - 1; 295 reg_frame_bus = 0x07; 296 fmt_reg_value = 1; 297 downscale_enabled = 1; 298 input->reg_dsp_codec |= TW5864_CIF_MAP_MD; 299 300 tw_clearl(TW5864_FULL_HALF_FLAG, 1 << nr); 301 break; 302 case QCIF: 303 input->height /= 4; 304 input->width /= 4; 305 frame_width_bus_value = 0x15f; 306 frame_height_bus_value = input->height * 2 - 1; 307 reg_frame_bus = 0x07; 308 fmt_reg_value = 1; 309 downscale_enabled = 1; 310 input->reg_dsp_codec |= TW5864_CIF_MAP_MD; 311 312 tw_clearl(TW5864_FULL_HALF_FLAG, 1 << nr); 313 break; 314 } 315 316 /* analog input width / 4 */ 317 tw_indir_writeb(TW5864_INDIR_IN_PIC_WIDTH(nr), d1_width / 4); 318 tw_indir_writeb(TW5864_INDIR_IN_PIC_HEIGHT(nr), d1_height / 4); 319 320 /* output width / 4 */ 321 tw_indir_writeb(TW5864_INDIR_OUT_PIC_WIDTH(nr), input->width / 4); 322 tw_indir_writeb(TW5864_INDIR_OUT_PIC_HEIGHT(nr), input->height / 4); 323 324 /* 325 * Crop width from 720 to 704. 326 * Above register settings need value 720 involved. 327 */ 328 input->width = 704; 329 tw_indir_writeb(TW5864_INDIR_CROP_ETC, 330 tw_indir_readb(TW5864_INDIR_CROP_ETC) | 331 TW5864_INDIR_CROP_ETC_CROP_EN); 332 333 tw_writel(TW5864_DSP_PIC_MAX_MB, 334 ((input->width / 16) << 8) | (input->height / 16)); 335 336 tw_writel(TW5864_FRAME_WIDTH_BUS_A(nr), 337 frame_width_bus_value); 338 tw_writel(TW5864_FRAME_WIDTH_BUS_B(nr), 339 frame_width_bus_value); 340 tw_writel(TW5864_FRAME_HEIGHT_BUS_A(nr), 341 frame_height_bus_value); 342 tw_writel(TW5864_FRAME_HEIGHT_BUS_B(nr), 343 (frame_height_bus_value + 1) / 2 - 1); 344 345 tw5864_frame_interval_set(input); 346 347 if (downscale_enabled) 348 tw_setl(TW5864_H264EN_CH_DNS, 1 << nr); 349 350 tw_mask_shift_writel(TW5864_H264EN_CH_FMT_REG1, 0x3, 2 * nr, 351 fmt_reg_value); 352 353 tw_mask_shift_writel((nr < 2 354 ? TW5864_H264EN_RATE_MAX_LINE_REG1 355 : TW5864_H264EN_RATE_MAX_LINE_REG2), 356 0x1f, 5 * (nr % 2), 357 input->std == STD_NTSC ? 29 : 24); 358 359 tw_mask_shift_writel((nr < 2) ? TW5864_FRAME_BUS1 : 360 TW5864_FRAME_BUS2, 0xff, (nr % 2) * 8, 361 reg_frame_bus); 362 363 spin_lock_irqsave(&dev->slock, flags); 364 input->enabled = 1; 365 spin_unlock_irqrestore(&dev->slock, flags); 366 367 return 0; 368 } 369 370 void tw5864_request_encoded_frame(struct tw5864_input *input) 371 { 372 struct tw5864_dev *dev = input->root; 373 u32 enc_buf_id_new; 374 375 tw_setl(TW5864_DSP_CODEC, TW5864_CIF_MAP_MD | TW5864_HD1_MAP_MD); 376 tw_writel(TW5864_EMU, input->reg_emu); 377 tw_writel(TW5864_INTERLACING, input->reg_interlacing); 378 tw_writel(TW5864_DSP, input->reg_dsp); 379 380 tw_writel(TW5864_DSP_QP, input->reg_dsp_qp); 381 tw_writel(TW5864_DSP_REF_MVP_LAMBDA, input->reg_dsp_ref_mvp_lambda); 382 tw_writel(TW5864_DSP_I4x4_WEIGHT, input->reg_dsp_i4x4_weight); 383 tw_mask_shift_writel(TW5864_DSP_INTRA_MODE, TW5864_DSP_INTRA_MODE_MASK, 384 TW5864_DSP_INTRA_MODE_SHIFT, 385 TW5864_DSP_INTRA_MODE_16x16); 386 387 if (input->frame_gop_seqno == 0) { 388 /* Produce I-frame */ 389 tw_writel(TW5864_MOTION_SEARCH_ETC, TW5864_INTRA_EN); 390 input->h264_idr_pic_id++; 391 input->h264_idr_pic_id &= TW5864_DSP_REF_FRM; 392 } else { 393 /* Produce P-frame */ 394 tw_writel(TW5864_MOTION_SEARCH_ETC, TW5864_INTRA_EN | 395 TW5864_ME_EN | BIT(5) /* SRCH_OPT default */); 396 } 397 tw5864_prepare_frame_headers(input); 398 tw_writel(TW5864_VLC, 399 TW5864_VLC_PCI_SEL | 400 ((input->tail_nb_bits + 24) << TW5864_VLC_BIT_ALIGN_SHIFT) | 401 input->reg_dsp_qp); 402 403 enc_buf_id_new = tw_mask_shift_readl(TW5864_ENC_BUF_PTR_REC1, 0x3, 404 2 * input->nr); 405 tw_writel(TW5864_DSP_ENC_ORG_PTR_REG, 406 enc_buf_id_new << TW5864_DSP_ENC_ORG_PTR_SHIFT); 407 tw_writel(TW5864_DSP_ENC_REC, 408 enc_buf_id_new << 12 | ((enc_buf_id_new + 3) & 3)); 409 410 tw_writel(TW5864_SLICE, TW5864_START_NSLICE); 411 tw_writel(TW5864_SLICE, 0); 412 } 413 414 static int tw5864_disable_input(struct tw5864_input *input) 415 { 416 struct tw5864_dev *dev = input->root; 417 unsigned long flags; 418 419 dev_dbg(&dev->pci->dev, "Disabling channel %d\n", input->nr); 420 421 spin_lock_irqsave(&dev->slock, flags); 422 input->enabled = 0; 423 spin_unlock_irqrestore(&dev->slock, flags); 424 return 0; 425 } 426 427 static int tw5864_start_streaming(struct vb2_queue *q, unsigned int count) 428 { 429 struct tw5864_input *input = vb2_get_drv_priv(q); 430 int ret; 431 432 ret = tw5864_enable_input(input); 433 if (!ret) 434 return 0; 435 436 while (!list_empty(&input->active)) { 437 struct tw5864_buf *buf = list_entry(input->active.next, 438 struct tw5864_buf, list); 439 440 list_del(&buf->list); 441 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED); 442 } 443 return ret; 444 } 445 446 static void tw5864_stop_streaming(struct vb2_queue *q) 447 { 448 unsigned long flags; 449 struct tw5864_input *input = vb2_get_drv_priv(q); 450 451 tw5864_disable_input(input); 452 453 spin_lock_irqsave(&input->slock, flags); 454 if (input->vb) { 455 vb2_buffer_done(&input->vb->vb.vb2_buf, VB2_BUF_STATE_ERROR); 456 input->vb = NULL; 457 } 458 while (!list_empty(&input->active)) { 459 struct tw5864_buf *buf = list_entry(input->active.next, 460 struct tw5864_buf, list); 461 462 list_del(&buf->list); 463 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); 464 } 465 spin_unlock_irqrestore(&input->slock, flags); 466 } 467 468 static const struct vb2_ops tw5864_video_qops = { 469 .queue_setup = tw5864_queue_setup, 470 .buf_queue = tw5864_buf_queue, 471 .start_streaming = tw5864_start_streaming, 472 .stop_streaming = tw5864_stop_streaming, 473 .wait_prepare = vb2_ops_wait_prepare, 474 .wait_finish = vb2_ops_wait_finish, 475 }; 476 477 static int tw5864_s_ctrl(struct v4l2_ctrl *ctrl) 478 { 479 struct tw5864_input *input = 480 container_of(ctrl->handler, struct tw5864_input, hdl); 481 struct tw5864_dev *dev = input->root; 482 unsigned long flags; 483 484 switch (ctrl->id) { 485 case V4L2_CID_BRIGHTNESS: 486 tw_indir_writeb(TW5864_INDIR_VIN_A_BRIGHT(input->nr), 487 (u8)ctrl->val); 488 break; 489 case V4L2_CID_HUE: 490 tw_indir_writeb(TW5864_INDIR_VIN_7_HUE(input->nr), 491 (u8)ctrl->val); 492 break; 493 case V4L2_CID_CONTRAST: 494 tw_indir_writeb(TW5864_INDIR_VIN_9_CNTRST(input->nr), 495 (u8)ctrl->val); 496 break; 497 case V4L2_CID_SATURATION: 498 tw_indir_writeb(TW5864_INDIR_VIN_B_SAT_U(input->nr), 499 (u8)ctrl->val); 500 tw_indir_writeb(TW5864_INDIR_VIN_C_SAT_V(input->nr), 501 (u8)ctrl->val); 502 break; 503 case V4L2_CID_MPEG_VIDEO_GOP_SIZE: 504 input->gop = ctrl->val; 505 return 0; 506 case V4L2_CID_MPEG_VIDEO_H264_MIN_QP: 507 spin_lock_irqsave(&input->slock, flags); 508 input->qp = ctrl->val; 509 input->reg_dsp_qp = input->qp; 510 input->reg_dsp_ref_mvp_lambda = lambda_lookup_table[input->qp]; 511 input->reg_dsp_i4x4_weight = intra4x4_lambda3[input->qp]; 512 spin_unlock_irqrestore(&input->slock, flags); 513 return 0; 514 case V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD: 515 memset(input->md_threshold_grid_values, ctrl->val, 516 sizeof(input->md_threshold_grid_values)); 517 return 0; 518 case V4L2_CID_DETECT_MD_MODE: 519 return 0; 520 case V4L2_CID_DETECT_MD_THRESHOLD_GRID: 521 /* input->md_threshold_grid_ctrl->p_new.p_u16 contains data */ 522 memcpy(input->md_threshold_grid_values, 523 input->md_threshold_grid_ctrl->p_new.p_u16, 524 sizeof(input->md_threshold_grid_values)); 525 return 0; 526 } 527 return 0; 528 } 529 530 static int tw5864_fmt_vid_cap(struct file *file, void *priv, 531 struct v4l2_format *f) 532 { 533 struct tw5864_input *input = video_drvdata(file); 534 535 f->fmt.pix.width = 704; 536 switch (input->std) { 537 default: 538 WARN_ON_ONCE(1); 539 return -EINVAL; 540 case STD_NTSC: 541 f->fmt.pix.height = 480; 542 break; 543 case STD_PAL: 544 case STD_SECAM: 545 f->fmt.pix.height = 576; 546 break; 547 } 548 f->fmt.pix.field = V4L2_FIELD_INTERLACED; 549 f->fmt.pix.pixelformat = V4L2_PIX_FMT_H264; 550 f->fmt.pix.sizeimage = H264_VLC_BUF_SIZE; 551 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; 552 return 0; 553 } 554 555 static int tw5864_enum_input(struct file *file, void *priv, 556 struct v4l2_input *i) 557 { 558 struct tw5864_input *input = video_drvdata(file); 559 struct tw5864_dev *dev = input->root; 560 561 u8 indir_0x000 = tw_indir_readb(TW5864_INDIR_VIN_0(input->nr)); 562 u8 indir_0x00d = tw_indir_readb(TW5864_INDIR_VIN_D(input->nr)); 563 u8 v1 = indir_0x000; 564 u8 v2 = indir_0x00d; 565 566 if (i->index) 567 return -EINVAL; 568 569 i->type = V4L2_INPUT_TYPE_CAMERA; 570 snprintf(i->name, sizeof(i->name), "Encoder %d", input->nr); 571 i->std = TW5864_NORMS; 572 if (v1 & (1 << 7)) 573 i->status |= V4L2_IN_ST_NO_SYNC; 574 if (!(v1 & (1 << 6))) 575 i->status |= V4L2_IN_ST_NO_H_LOCK; 576 if (v1 & (1 << 2)) 577 i->status |= V4L2_IN_ST_NO_SIGNAL; 578 if (v1 & (1 << 1)) 579 i->status |= V4L2_IN_ST_NO_COLOR; 580 if (v2 & (1 << 2)) 581 i->status |= V4L2_IN_ST_MACROVISION; 582 583 return 0; 584 } 585 586 static int tw5864_g_input(struct file *file, void *priv, unsigned int *i) 587 { 588 *i = 0; 589 return 0; 590 } 591 592 static int tw5864_s_input(struct file *file, void *priv, unsigned int i) 593 { 594 if (i) 595 return -EINVAL; 596 return 0; 597 } 598 599 static int tw5864_querycap(struct file *file, void *priv, 600 struct v4l2_capability *cap) 601 { 602 struct tw5864_input *input = video_drvdata(file); 603 604 strscpy(cap->driver, "tw5864", sizeof(cap->driver)); 605 snprintf(cap->card, sizeof(cap->card), "TW5864 Encoder %d", 606 input->nr); 607 sprintf(cap->bus_info, "PCI:%s", pci_name(input->root->pci)); 608 return 0; 609 } 610 611 static int tw5864_querystd(struct file *file, void *priv, v4l2_std_id *std) 612 { 613 struct tw5864_input *input = video_drvdata(file); 614 enum tw5864_vid_std tw_std; 615 int ret; 616 617 ret = tw5864_input_std_get(input, &tw_std); 618 if (ret) 619 return ret; 620 *std = tw5864_get_v4l2_std(tw_std); 621 622 return 0; 623 } 624 625 static int tw5864_g_std(struct file *file, void *priv, v4l2_std_id *std) 626 { 627 struct tw5864_input *input = video_drvdata(file); 628 629 *std = input->v4l2_std; 630 return 0; 631 } 632 633 static int tw5864_s_std(struct file *file, void *priv, v4l2_std_id std) 634 { 635 struct tw5864_input *input = video_drvdata(file); 636 struct tw5864_dev *dev = input->root; 637 638 input->v4l2_std = std; 639 input->std = tw5864_from_v4l2_std(std); 640 tw_indir_writeb(TW5864_INDIR_VIN_E(input->nr), input->std); 641 return 0; 642 } 643 644 static int tw5864_enum_fmt_vid_cap(struct file *file, void *priv, 645 struct v4l2_fmtdesc *f) 646 { 647 if (f->index) 648 return -EINVAL; 649 650 f->pixelformat = V4L2_PIX_FMT_H264; 651 652 return 0; 653 } 654 655 static int tw5864_subscribe_event(struct v4l2_fh *fh, 656 const struct v4l2_event_subscription *sub) 657 { 658 switch (sub->type) { 659 case V4L2_EVENT_MOTION_DET: 660 /* 661 * Allow for up to 30 events (1 second for NTSC) to be stored. 662 */ 663 return v4l2_event_subscribe(fh, sub, 30, NULL); 664 default: 665 return v4l2_ctrl_subscribe_event(fh, sub); 666 } 667 } 668 669 static void tw5864_frame_interval_set(struct tw5864_input *input) 670 { 671 /* 672 * This register value seems to follow such approach: In each second 673 * interval, when processing Nth frame, it checks Nth bit of register 674 * value and, if the bit is 1, it processes the frame, otherwise the 675 * frame is discarded. 676 * So unary representation would work, but more or less equal gaps 677 * between the frames should be preserved. 678 * 679 * For 1 FPS - 0x00000001 680 * 00000000 00000000 00000000 00000001 681 * 682 * For max FPS - set all 25/30 lower bits: 683 * 00111111 11111111 11111111 11111111 (NTSC) 684 * 00000001 11111111 11111111 11111111 (PAL) 685 * 686 * For half of max FPS - use such pattern: 687 * 00010101 01010101 01010101 01010101 (NTSC) 688 * 00000001 01010101 01010101 01010101 (PAL) 689 * 690 * Et cetera. 691 * 692 * The value supplied to hardware is capped by mask of 25/30 lower bits. 693 */ 694 struct tw5864_dev *dev = input->root; 695 u32 unary_framerate = 0; 696 int shift = 0; 697 int std_max_fps = input->std == STD_NTSC ? 30 : 25; 698 699 for (shift = 0; shift < std_max_fps; shift += input->frame_interval) 700 unary_framerate |= 0x00000001 << shift; 701 702 tw_writel(TW5864_H264EN_RATE_CNTL_LO_WORD(input->nr, 0), 703 unary_framerate >> 16); 704 tw_writel(TW5864_H264EN_RATE_CNTL_HI_WORD(input->nr, 0), 705 unary_framerate & 0xffff); 706 } 707 708 static int tw5864_frameinterval_get(struct tw5864_input *input, 709 struct v4l2_fract *frameinterval) 710 { 711 struct tw5864_dev *dev = input->root; 712 713 switch (input->std) { 714 case STD_NTSC: 715 frameinterval->numerator = 1001; 716 frameinterval->denominator = 30000; 717 break; 718 case STD_PAL: 719 case STD_SECAM: 720 frameinterval->numerator = 1; 721 frameinterval->denominator = 25; 722 break; 723 default: 724 dev_warn(&dev->pci->dev, "tw5864_frameinterval_get requested for unknown std %d\n", 725 input->std); 726 return -EINVAL; 727 } 728 729 return 0; 730 } 731 732 static int tw5864_enum_framesizes(struct file *file, void *priv, 733 struct v4l2_frmsizeenum *fsize) 734 { 735 struct tw5864_input *input = video_drvdata(file); 736 737 if (fsize->index > 0) 738 return -EINVAL; 739 if (fsize->pixel_format != V4L2_PIX_FMT_H264) 740 return -EINVAL; 741 742 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; 743 fsize->discrete.width = 704; 744 fsize->discrete.height = input->std == STD_NTSC ? 480 : 576; 745 746 return 0; 747 } 748 749 static int tw5864_enum_frameintervals(struct file *file, void *priv, 750 struct v4l2_frmivalenum *fintv) 751 { 752 struct tw5864_input *input = video_drvdata(file); 753 struct v4l2_fract frameinterval; 754 int std_max_fps = input->std == STD_NTSC ? 30 : 25; 755 struct v4l2_frmsizeenum fsize = { .index = fintv->index, 756 .pixel_format = fintv->pixel_format }; 757 int ret; 758 759 ret = tw5864_enum_framesizes(file, priv, &fsize); 760 if (ret) 761 return ret; 762 763 if (fintv->width != fsize.discrete.width || 764 fintv->height != fsize.discrete.height) 765 return -EINVAL; 766 767 fintv->type = V4L2_FRMIVAL_TYPE_STEPWISE; 768 769 ret = tw5864_frameinterval_get(input, &frameinterval); 770 fintv->stepwise.step = frameinterval; 771 fintv->stepwise.min = frameinterval; 772 fintv->stepwise.max = frameinterval; 773 fintv->stepwise.max.numerator *= std_max_fps; 774 775 return ret; 776 } 777 778 static int tw5864_g_parm(struct file *file, void *priv, 779 struct v4l2_streamparm *sp) 780 { 781 struct tw5864_input *input = video_drvdata(file); 782 struct v4l2_captureparm *cp = &sp->parm.capture; 783 int ret; 784 785 cp->capability = V4L2_CAP_TIMEPERFRAME; 786 787 ret = tw5864_frameinterval_get(input, &cp->timeperframe); 788 cp->timeperframe.numerator *= input->frame_interval; 789 cp->capturemode = 0; 790 cp->readbuffers = 2; 791 792 return ret; 793 } 794 795 static int tw5864_s_parm(struct file *file, void *priv, 796 struct v4l2_streamparm *sp) 797 { 798 struct tw5864_input *input = video_drvdata(file); 799 struct v4l2_fract *t = &sp->parm.capture.timeperframe; 800 struct v4l2_fract time_base; 801 int ret; 802 803 ret = tw5864_frameinterval_get(input, &time_base); 804 if (ret) 805 return ret; 806 807 if (!t->numerator || !t->denominator) { 808 t->numerator = time_base.numerator * input->frame_interval; 809 t->denominator = time_base.denominator; 810 } else if (t->denominator != time_base.denominator) { 811 t->numerator = t->numerator * time_base.denominator / 812 t->denominator; 813 t->denominator = time_base.denominator; 814 } 815 816 input->frame_interval = t->numerator / time_base.numerator; 817 if (input->frame_interval < 1) 818 input->frame_interval = 1; 819 tw5864_frame_interval_set(input); 820 return tw5864_g_parm(file, priv, sp); 821 } 822 823 static const struct v4l2_ctrl_ops tw5864_ctrl_ops = { 824 .s_ctrl = tw5864_s_ctrl, 825 }; 826 827 static const struct v4l2_file_operations video_fops = { 828 .owner = THIS_MODULE, 829 .open = v4l2_fh_open, 830 .release = vb2_fop_release, 831 .read = vb2_fop_read, 832 .poll = vb2_fop_poll, 833 .mmap = vb2_fop_mmap, 834 .unlocked_ioctl = video_ioctl2, 835 }; 836 837 #ifdef CONFIG_VIDEO_ADV_DEBUG 838 839 #define INDIR_SPACE_MAP_SHIFT 0x100000 840 841 static int tw5864_g_reg(struct file *file, void *fh, 842 struct v4l2_dbg_register *reg) 843 { 844 struct tw5864_input *input = video_drvdata(file); 845 struct tw5864_dev *dev = input->root; 846 847 if (reg->reg < INDIR_SPACE_MAP_SHIFT) { 848 if (reg->reg > 0x87fff) 849 return -EINVAL; 850 reg->size = 4; 851 reg->val = tw_readl(reg->reg); 852 } else { 853 __u64 indir_addr = reg->reg - INDIR_SPACE_MAP_SHIFT; 854 855 if (indir_addr > 0xefe) 856 return -EINVAL; 857 reg->size = 1; 858 reg->val = tw_indir_readb(reg->reg); 859 } 860 return 0; 861 } 862 863 static int tw5864_s_reg(struct file *file, void *fh, 864 const struct v4l2_dbg_register *reg) 865 { 866 struct tw5864_input *input = video_drvdata(file); 867 struct tw5864_dev *dev = input->root; 868 869 if (reg->reg < INDIR_SPACE_MAP_SHIFT) { 870 if (reg->reg > 0x87fff) 871 return -EINVAL; 872 tw_writel(reg->reg, reg->val); 873 } else { 874 __u64 indir_addr = reg->reg - INDIR_SPACE_MAP_SHIFT; 875 876 if (indir_addr > 0xefe) 877 return -EINVAL; 878 tw_indir_writeb(reg->reg, reg->val); 879 } 880 return 0; 881 } 882 #endif 883 884 static const struct v4l2_ioctl_ops video_ioctl_ops = { 885 .vidioc_querycap = tw5864_querycap, 886 .vidioc_enum_fmt_vid_cap = tw5864_enum_fmt_vid_cap, 887 .vidioc_reqbufs = vb2_ioctl_reqbufs, 888 .vidioc_create_bufs = vb2_ioctl_create_bufs, 889 .vidioc_querybuf = vb2_ioctl_querybuf, 890 .vidioc_qbuf = vb2_ioctl_qbuf, 891 .vidioc_dqbuf = vb2_ioctl_dqbuf, 892 .vidioc_expbuf = vb2_ioctl_expbuf, 893 .vidioc_querystd = tw5864_querystd, 894 .vidioc_s_std = tw5864_s_std, 895 .vidioc_g_std = tw5864_g_std, 896 .vidioc_enum_input = tw5864_enum_input, 897 .vidioc_g_input = tw5864_g_input, 898 .vidioc_s_input = tw5864_s_input, 899 .vidioc_streamon = vb2_ioctl_streamon, 900 .vidioc_streamoff = vb2_ioctl_streamoff, 901 .vidioc_try_fmt_vid_cap = tw5864_fmt_vid_cap, 902 .vidioc_s_fmt_vid_cap = tw5864_fmt_vid_cap, 903 .vidioc_g_fmt_vid_cap = tw5864_fmt_vid_cap, 904 .vidioc_log_status = v4l2_ctrl_log_status, 905 .vidioc_subscribe_event = tw5864_subscribe_event, 906 .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 907 .vidioc_enum_framesizes = tw5864_enum_framesizes, 908 .vidioc_enum_frameintervals = tw5864_enum_frameintervals, 909 .vidioc_s_parm = tw5864_s_parm, 910 .vidioc_g_parm = tw5864_g_parm, 911 #ifdef CONFIG_VIDEO_ADV_DEBUG 912 .vidioc_g_register = tw5864_g_reg, 913 .vidioc_s_register = tw5864_s_reg, 914 #endif 915 }; 916 917 static const struct video_device tw5864_video_template = { 918 .name = "tw5864_video", 919 .fops = &video_fops, 920 .ioctl_ops = &video_ioctl_ops, 921 .release = video_device_release_empty, 922 .tvnorms = TW5864_NORMS, 923 .device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | 924 V4L2_CAP_STREAMING, 925 }; 926 927 /* Motion Detection Threshold matrix */ 928 static const struct v4l2_ctrl_config tw5864_md_thresholds = { 929 .ops = &tw5864_ctrl_ops, 930 .id = V4L2_CID_DETECT_MD_THRESHOLD_GRID, 931 .dims = {MD_CELLS_HOR, MD_CELLS_VERT}, 932 .def = 14, 933 /* See tw5864_md_metric_from_mvd() */ 934 .max = 2 * 0x0f, 935 .step = 1, 936 }; 937 938 static int tw5864_video_input_init(struct tw5864_input *dev, int video_nr); 939 static void tw5864_video_input_fini(struct tw5864_input *dev); 940 static void tw5864_encoder_tables_upload(struct tw5864_dev *dev); 941 942 int tw5864_video_init(struct tw5864_dev *dev, int *video_nr) 943 { 944 int i; 945 int ret; 946 unsigned long flags; 947 int last_dma_allocated = -1; 948 int last_input_nr_registered = -1; 949 950 for (i = 0; i < H264_BUF_CNT; i++) { 951 struct tw5864_h264_frame *frame = &dev->h264_buf[i]; 952 953 frame->vlc.addr = dma_alloc_coherent(&dev->pci->dev, 954 H264_VLC_BUF_SIZE, 955 &frame->vlc.dma_addr, 956 GFP_KERNEL | GFP_DMA32); 957 if (!frame->vlc.addr) { 958 dev_err(&dev->pci->dev, "dma alloc fail\n"); 959 ret = -ENOMEM; 960 goto free_dma; 961 } 962 frame->mv.addr = dma_alloc_coherent(&dev->pci->dev, 963 H264_MV_BUF_SIZE, 964 &frame->mv.dma_addr, 965 GFP_KERNEL | GFP_DMA32); 966 if (!frame->mv.addr) { 967 dev_err(&dev->pci->dev, "dma alloc fail\n"); 968 ret = -ENOMEM; 969 dma_free_coherent(&dev->pci->dev, H264_VLC_BUF_SIZE, 970 frame->vlc.addr, frame->vlc.dma_addr); 971 goto free_dma; 972 } 973 last_dma_allocated = i; 974 } 975 976 tw5864_encoder_tables_upload(dev); 977 978 /* Picture is distorted without this block */ 979 /* use falling edge to sample 54M to 108M */ 980 tw_indir_writeb(TW5864_INDIR_VD_108_POL, TW5864_INDIR_VD_108_POL_BOTH); 981 tw_indir_writeb(TW5864_INDIR_CLK0_SEL, 0x00); 982 983 tw_indir_writeb(TW5864_INDIR_DDRA_DLL_DQS_SEL0, 0x02); 984 tw_indir_writeb(TW5864_INDIR_DDRA_DLL_DQS_SEL1, 0x02); 985 tw_indir_writeb(TW5864_INDIR_DDRA_DLL_CLK90_SEL, 0x02); 986 tw_indir_writeb(TW5864_INDIR_DDRB_DLL_DQS_SEL0, 0x02); 987 tw_indir_writeb(TW5864_INDIR_DDRB_DLL_DQS_SEL1, 0x02); 988 tw_indir_writeb(TW5864_INDIR_DDRB_DLL_CLK90_SEL, 0x02); 989 990 /* video input reset */ 991 tw_indir_writeb(TW5864_INDIR_RESET, 0); 992 tw_indir_writeb(TW5864_INDIR_RESET, TW5864_INDIR_RESET_VD | 993 TW5864_INDIR_RESET_DLL | TW5864_INDIR_RESET_MUX_CORE); 994 msleep(20); 995 996 /* 997 * Select Part A mode for all channels. 998 * tw_setl instead of tw_clearl for Part B mode. 999 * 1000 * I guess "Part B" is primarily for downscaled version of same channel 1001 * which goes in Part A of same bus 1002 */ 1003 tw_writel(TW5864_FULL_HALF_MODE_SEL, 0); 1004 1005 tw_indir_writeb(TW5864_INDIR_PV_VD_CK_POL, 1006 TW5864_INDIR_PV_VD_CK_POL_VD(0) | 1007 TW5864_INDIR_PV_VD_CK_POL_VD(1) | 1008 TW5864_INDIR_PV_VD_CK_POL_VD(2) | 1009 TW5864_INDIR_PV_VD_CK_POL_VD(3)); 1010 1011 spin_lock_irqsave(&dev->slock, flags); 1012 dev->encoder_busy = 0; 1013 dev->h264_buf_r_index = 0; 1014 dev->h264_buf_w_index = 0; 1015 tw_writel(TW5864_VLC_STREAM_BASE_ADDR, 1016 dev->h264_buf[dev->h264_buf_w_index].vlc.dma_addr); 1017 tw_writel(TW5864_MV_STREAM_BASE_ADDR, 1018 dev->h264_buf[dev->h264_buf_w_index].mv.dma_addr); 1019 spin_unlock_irqrestore(&dev->slock, flags); 1020 1021 tw_writel(TW5864_SEN_EN_CH, 0x000f); 1022 tw_writel(TW5864_H264EN_CH_EN, 0x000f); 1023 1024 tw_writel(TW5864_H264EN_BUS0_MAP, 0x00000000); 1025 tw_writel(TW5864_H264EN_BUS1_MAP, 0x00001111); 1026 tw_writel(TW5864_H264EN_BUS2_MAP, 0x00002222); 1027 tw_writel(TW5864_H264EN_BUS3_MAP, 0x00003333); 1028 1029 /* 1030 * Quote from Intersil (manufacturer): 1031 * 0x0038 is managed by HW, and by default it won't pass the pointer set 1032 * at 0x0010. So if you don't do encoding, 0x0038 should stay at '3' 1033 * (with 4 frames in buffer). If you encode one frame and then move 1034 * 0x0010 to '1' for example, HW will take one more frame and set it to 1035 * buffer #0, and then you should see 0x0038 is set to '0'. There is 1036 * only one HW encoder engine, so 4 channels cannot get encoded 1037 * simultaneously. But each channel does have its own buffer (for 1038 * original frames and reconstructed frames). So there is no problem to 1039 * manage encoding for 4 channels at same time and no need to force 1040 * I-frames in switching channels. 1041 * End of quote. 1042 * 1043 * If we set 0x0010 (TW5864_ENC_BUF_PTR_REC1) to 0 (for any channel), we 1044 * have no "rolling" (until we change this value). 1045 * If we set 0x0010 (TW5864_ENC_BUF_PTR_REC1) to 0x3, it starts to roll 1046 * continuously together with 0x0038. 1047 */ 1048 tw_writel(TW5864_ENC_BUF_PTR_REC1, 0x00ff); 1049 tw_writel(TW5864_PCI_INTTM_SCALE, 0); 1050 1051 tw_writel(TW5864_INTERLACING, TW5864_DI_EN); 1052 tw_writel(TW5864_MASTER_ENB_REG, TW5864_PCI_VLC_INTR_ENB); 1053 tw_writel(TW5864_PCI_INTR_CTL, 1054 TW5864_TIMER_INTR_ENB | TW5864_PCI_MAST_ENB | 1055 TW5864_MVD_VLC_MAST_ENB); 1056 1057 dev->irqmask |= TW5864_INTR_VLC_DONE | TW5864_INTR_TIMER; 1058 tw5864_irqmask_apply(dev); 1059 1060 tasklet_setup(&dev->tasklet, tw5864_handle_frame_task); 1061 1062 for (i = 0; i < TW5864_INPUTS; i++) { 1063 dev->inputs[i].root = dev; 1064 dev->inputs[i].nr = i; 1065 ret = tw5864_video_input_init(&dev->inputs[i], video_nr[i]); 1066 if (ret) 1067 goto fini_video_inputs; 1068 last_input_nr_registered = i; 1069 } 1070 1071 return 0; 1072 1073 fini_video_inputs: 1074 for (i = last_input_nr_registered; i >= 0; i--) 1075 tw5864_video_input_fini(&dev->inputs[i]); 1076 1077 tasklet_kill(&dev->tasklet); 1078 1079 free_dma: 1080 for (i = last_dma_allocated; i >= 0; i--) { 1081 dma_free_coherent(&dev->pci->dev, H264_VLC_BUF_SIZE, 1082 dev->h264_buf[i].vlc.addr, 1083 dev->h264_buf[i].vlc.dma_addr); 1084 dma_free_coherent(&dev->pci->dev, H264_MV_BUF_SIZE, 1085 dev->h264_buf[i].mv.addr, 1086 dev->h264_buf[i].mv.dma_addr); 1087 } 1088 1089 return ret; 1090 } 1091 1092 static int tw5864_video_input_init(struct tw5864_input *input, int video_nr) 1093 { 1094 struct tw5864_dev *dev = input->root; 1095 int ret; 1096 struct v4l2_ctrl_handler *hdl = &input->hdl; 1097 1098 mutex_init(&input->lock); 1099 spin_lock_init(&input->slock); 1100 1101 /* setup video buffers queue */ 1102 INIT_LIST_HEAD(&input->active); 1103 input->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1104 input->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; 1105 input->vidq.io_modes = VB2_MMAP | VB2_READ | VB2_DMABUF; 1106 input->vidq.ops = &tw5864_video_qops; 1107 input->vidq.mem_ops = &vb2_dma_contig_memops; 1108 input->vidq.drv_priv = input; 1109 input->vidq.gfp_flags = 0; 1110 input->vidq.buf_struct_size = sizeof(struct tw5864_buf); 1111 input->vidq.lock = &input->lock; 1112 input->vidq.min_buffers_needed = 2; 1113 input->vidq.dev = &input->root->pci->dev; 1114 ret = vb2_queue_init(&input->vidq); 1115 if (ret) 1116 goto free_mutex; 1117 1118 input->vdev = tw5864_video_template; 1119 input->vdev.v4l2_dev = &input->root->v4l2_dev; 1120 input->vdev.lock = &input->lock; 1121 input->vdev.queue = &input->vidq; 1122 video_set_drvdata(&input->vdev, input); 1123 1124 /* Initialize the device control structures */ 1125 v4l2_ctrl_handler_init(hdl, 6); 1126 v4l2_ctrl_new_std(hdl, &tw5864_ctrl_ops, 1127 V4L2_CID_BRIGHTNESS, -128, 127, 1, 0); 1128 v4l2_ctrl_new_std(hdl, &tw5864_ctrl_ops, 1129 V4L2_CID_CONTRAST, 0, 255, 1, 100); 1130 v4l2_ctrl_new_std(hdl, &tw5864_ctrl_ops, 1131 V4L2_CID_SATURATION, 0, 255, 1, 128); 1132 v4l2_ctrl_new_std(hdl, &tw5864_ctrl_ops, V4L2_CID_HUE, -128, 127, 1, 0); 1133 v4l2_ctrl_new_std(hdl, &tw5864_ctrl_ops, V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1134 1, MAX_GOP_SIZE, 1, GOP_SIZE); 1135 v4l2_ctrl_new_std(hdl, &tw5864_ctrl_ops, 1136 V4L2_CID_MPEG_VIDEO_H264_MIN_QP, 28, 51, 1, QP_VALUE); 1137 v4l2_ctrl_new_std_menu(hdl, &tw5864_ctrl_ops, 1138 V4L2_CID_DETECT_MD_MODE, 1139 V4L2_DETECT_MD_MODE_THRESHOLD_GRID, 0, 1140 V4L2_DETECT_MD_MODE_DISABLED); 1141 v4l2_ctrl_new_std(hdl, &tw5864_ctrl_ops, 1142 V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD, 1143 tw5864_md_thresholds.min, tw5864_md_thresholds.max, 1144 tw5864_md_thresholds.step, tw5864_md_thresholds.def); 1145 input->md_threshold_grid_ctrl = 1146 v4l2_ctrl_new_custom(hdl, &tw5864_md_thresholds, NULL); 1147 if (hdl->error) { 1148 ret = hdl->error; 1149 goto free_v4l2_hdl; 1150 } 1151 input->vdev.ctrl_handler = hdl; 1152 v4l2_ctrl_handler_setup(hdl); 1153 1154 input->qp = QP_VALUE; 1155 input->gop = GOP_SIZE; 1156 input->frame_interval = 1; 1157 1158 ret = video_register_device(&input->vdev, VFL_TYPE_VIDEO, video_nr); 1159 if (ret) 1160 goto free_v4l2_hdl; 1161 1162 dev_info(&input->root->pci->dev, "Registered video device %s\n", 1163 video_device_node_name(&input->vdev)); 1164 1165 /* 1166 * Set default video standard. Doesn't matter which, the detected value 1167 * will be found out by VIDIOC_QUERYSTD handler. 1168 */ 1169 input->v4l2_std = V4L2_STD_NTSC_M; 1170 input->std = STD_NTSC; 1171 1172 tw_indir_writeb(TW5864_INDIR_VIN_E(video_nr), 0x07); 1173 /* to initiate auto format recognition */ 1174 tw_indir_writeb(TW5864_INDIR_VIN_F(video_nr), 0xff); 1175 1176 return 0; 1177 1178 free_v4l2_hdl: 1179 v4l2_ctrl_handler_free(hdl); 1180 free_mutex: 1181 mutex_destroy(&input->lock); 1182 1183 return ret; 1184 } 1185 1186 static void tw5864_video_input_fini(struct tw5864_input *dev) 1187 { 1188 vb2_video_unregister_device(&dev->vdev); 1189 v4l2_ctrl_handler_free(&dev->hdl); 1190 } 1191 1192 void tw5864_video_fini(struct tw5864_dev *dev) 1193 { 1194 int i; 1195 1196 tasklet_kill(&dev->tasklet); 1197 1198 for (i = 0; i < TW5864_INPUTS; i++) 1199 tw5864_video_input_fini(&dev->inputs[i]); 1200 1201 for (i = 0; i < H264_BUF_CNT; i++) { 1202 dma_free_coherent(&dev->pci->dev, H264_VLC_BUF_SIZE, 1203 dev->h264_buf[i].vlc.addr, 1204 dev->h264_buf[i].vlc.dma_addr); 1205 dma_free_coherent(&dev->pci->dev, H264_MV_BUF_SIZE, 1206 dev->h264_buf[i].mv.addr, 1207 dev->h264_buf[i].mv.dma_addr); 1208 } 1209 } 1210 1211 void tw5864_prepare_frame_headers(struct tw5864_input *input) 1212 { 1213 struct tw5864_buf *vb = input->vb; 1214 u8 *dst; 1215 size_t dst_space; 1216 unsigned long flags; 1217 1218 if (!vb) { 1219 spin_lock_irqsave(&input->slock, flags); 1220 if (list_empty(&input->active)) { 1221 spin_unlock_irqrestore(&input->slock, flags); 1222 input->vb = NULL; 1223 return; 1224 } 1225 vb = list_first_entry(&input->active, struct tw5864_buf, list); 1226 list_del(&vb->list); 1227 spin_unlock_irqrestore(&input->slock, flags); 1228 } 1229 1230 dst = vb2_plane_vaddr(&vb->vb.vb2_buf, 0); 1231 dst_space = vb2_plane_size(&vb->vb.vb2_buf, 0); 1232 1233 /* 1234 * Low-level bitstream writing functions don't have a fine way to say 1235 * correctly that supplied buffer is too small. So we just check there 1236 * and warn, and don't care at lower level. 1237 * Currently all headers take below 32 bytes. 1238 * The buffer is supposed to have plenty of free space at this point, 1239 * anyway. 1240 */ 1241 if (WARN_ON_ONCE(dst_space < 128)) 1242 return; 1243 1244 /* 1245 * Generate H264 headers: 1246 * If this is first frame, put SPS and PPS 1247 */ 1248 if (input->frame_gop_seqno == 0) 1249 tw5864_h264_put_stream_header(&dst, &dst_space, input->qp, 1250 input->width, input->height); 1251 1252 /* Put slice header */ 1253 tw5864_h264_put_slice_header(&dst, &dst_space, input->h264_idr_pic_id, 1254 input->frame_gop_seqno, 1255 &input->tail_nb_bits, &input->tail); 1256 input->vb = vb; 1257 input->buf_cur_ptr = dst; 1258 input->buf_cur_space_left = dst_space; 1259 } 1260 1261 /* 1262 * Returns heuristic motion detection metric value from known components of 1263 * hardware-provided Motion Vector Data. 1264 */ 1265 static unsigned int tw5864_md_metric_from_mvd(u32 mvd) 1266 { 1267 /* 1268 * Format of motion vector data exposed by tw5864, according to 1269 * manufacturer: 1270 * mv_x 10 bits 1271 * mv_y 10 bits 1272 * non_zero_members 8 bits 1273 * mb_type 3 bits 1274 * reserved 1 bit 1275 * 1276 * non_zero_members: number of non-zero residuals in each macro block 1277 * after quantization 1278 * 1279 * unsigned int reserved = mvd >> 31; 1280 * unsigned int mb_type = (mvd >> 28) & 0x7; 1281 * unsigned int non_zero_members = (mvd >> 20) & 0xff; 1282 */ 1283 unsigned int mv_y = (mvd >> 10) & 0x3ff; 1284 unsigned int mv_x = mvd & 0x3ff; 1285 1286 /* heuristic: */ 1287 mv_x &= 0x0f; 1288 mv_y &= 0x0f; 1289 1290 return mv_y + mv_x; 1291 } 1292 1293 static int tw5864_is_motion_triggered(struct tw5864_h264_frame *frame) 1294 { 1295 struct tw5864_input *input = frame->input; 1296 u32 *mv = (u32 *)frame->mv.addr; 1297 int i; 1298 int detected = 0; 1299 1300 for (i = 0; i < MD_CELLS; i++) { 1301 const u16 thresh = input->md_threshold_grid_values[i]; 1302 const unsigned int metric = tw5864_md_metric_from_mvd(mv[i]); 1303 1304 if (metric > thresh) 1305 detected = 1; 1306 1307 if (detected) 1308 break; 1309 } 1310 return detected; 1311 } 1312 1313 static void tw5864_handle_frame_task(struct tasklet_struct *t) 1314 { 1315 struct tw5864_dev *dev = from_tasklet(dev, t, tasklet); 1316 unsigned long flags; 1317 int batch_size = H264_BUF_CNT; 1318 1319 spin_lock_irqsave(&dev->slock, flags); 1320 while (dev->h264_buf_r_index != dev->h264_buf_w_index && batch_size--) { 1321 struct tw5864_h264_frame *frame = 1322 &dev->h264_buf[dev->h264_buf_r_index]; 1323 1324 spin_unlock_irqrestore(&dev->slock, flags); 1325 dma_sync_single_for_cpu(&dev->pci->dev, frame->vlc.dma_addr, 1326 H264_VLC_BUF_SIZE, DMA_FROM_DEVICE); 1327 dma_sync_single_for_cpu(&dev->pci->dev, frame->mv.dma_addr, 1328 H264_MV_BUF_SIZE, DMA_FROM_DEVICE); 1329 tw5864_handle_frame(frame); 1330 dma_sync_single_for_device(&dev->pci->dev, frame->vlc.dma_addr, 1331 H264_VLC_BUF_SIZE, DMA_FROM_DEVICE); 1332 dma_sync_single_for_device(&dev->pci->dev, frame->mv.dma_addr, 1333 H264_MV_BUF_SIZE, DMA_FROM_DEVICE); 1334 spin_lock_irqsave(&dev->slock, flags); 1335 1336 dev->h264_buf_r_index++; 1337 dev->h264_buf_r_index %= H264_BUF_CNT; 1338 } 1339 spin_unlock_irqrestore(&dev->slock, flags); 1340 } 1341 1342 #ifdef DEBUG 1343 static u32 tw5864_vlc_checksum(u32 *data, int len) 1344 { 1345 u32 val, count_len = len; 1346 1347 val = *data++; 1348 while (((count_len >> 2) - 1) > 0) { 1349 val ^= *data++; 1350 count_len -= 4; 1351 } 1352 val ^= htonl((len >> 2)); 1353 return val; 1354 } 1355 #endif 1356 1357 static void tw5864_handle_frame(struct tw5864_h264_frame *frame) 1358 { 1359 #define SKIP_VLCBUF_BYTES 3 1360 struct tw5864_input *input = frame->input; 1361 struct tw5864_dev *dev = input->root; 1362 struct tw5864_buf *vb; 1363 struct vb2_v4l2_buffer *v4l2_buf; 1364 int frame_len = frame->vlc_len - SKIP_VLCBUF_BYTES; 1365 u8 *dst = input->buf_cur_ptr; 1366 u8 tail_mask, vlc_mask = 0; 1367 int i; 1368 u8 vlc_first_byte = ((u8 *)(frame->vlc.addr + SKIP_VLCBUF_BYTES))[0]; 1369 unsigned long flags; 1370 int zero_run; 1371 u8 *src; 1372 u8 *src_end; 1373 1374 #ifdef DEBUG 1375 if (frame->checksum != 1376 tw5864_vlc_checksum((u32 *)frame->vlc.addr, frame_len)) 1377 dev_err(&dev->pci->dev, 1378 "Checksum of encoded frame doesn't match!\n"); 1379 #endif 1380 1381 spin_lock_irqsave(&input->slock, flags); 1382 vb = input->vb; 1383 input->vb = NULL; 1384 spin_unlock_irqrestore(&input->slock, flags); 1385 1386 if (!vb) { /* Gone because of disabling */ 1387 dev_dbg(&dev->pci->dev, "vb is empty, dropping frame\n"); 1388 return; 1389 } 1390 1391 v4l2_buf = to_vb2_v4l2_buffer(&vb->vb.vb2_buf); 1392 1393 /* 1394 * Check for space. 1395 * Mind the overhead of startcode emulation prevention. 1396 */ 1397 if (input->buf_cur_space_left < frame_len * 5 / 4) { 1398 dev_err_once(&dev->pci->dev, 1399 "Left space in vb2 buffer, %d bytes, is less than considered safely enough to put frame of length %d. Dropping this frame.\n", 1400 input->buf_cur_space_left, frame_len); 1401 return; 1402 } 1403 1404 for (i = 0; i < 8 - input->tail_nb_bits; i++) 1405 vlc_mask |= 1 << i; 1406 tail_mask = (~vlc_mask) & 0xff; 1407 1408 dst[0] = (input->tail & tail_mask) | (vlc_first_byte & vlc_mask); 1409 frame_len--; 1410 dst++; 1411 1412 /* H.264 startcode emulation prevention */ 1413 src = frame->vlc.addr + SKIP_VLCBUF_BYTES + 1; 1414 src_end = src + frame_len; 1415 zero_run = 0; 1416 for (; src < src_end; src++) { 1417 if (zero_run < 2) { 1418 if (*src == 0) 1419 ++zero_run; 1420 else 1421 zero_run = 0; 1422 } else { 1423 if ((*src & ~0x03) == 0) 1424 *dst++ = 0x03; 1425 zero_run = *src == 0; 1426 } 1427 *dst++ = *src; 1428 } 1429 1430 vb2_set_plane_payload(&vb->vb.vb2_buf, 0, 1431 dst - (u8 *)vb2_plane_vaddr(&vb->vb.vb2_buf, 0)); 1432 1433 vb->vb.vb2_buf.timestamp = frame->timestamp; 1434 v4l2_buf->field = V4L2_FIELD_INTERLACED; 1435 v4l2_buf->sequence = frame->seqno; 1436 1437 /* Check for motion flags */ 1438 if (frame->gop_seqno /* P-frame */ && 1439 tw5864_is_motion_triggered(frame)) { 1440 struct v4l2_event ev = { 1441 .type = V4L2_EVENT_MOTION_DET, 1442 .u.motion_det = { 1443 .flags = V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ, 1444 .frame_sequence = v4l2_buf->sequence, 1445 }, 1446 }; 1447 1448 v4l2_event_queue(&input->vdev, &ev); 1449 } 1450 1451 vb2_buffer_done(&vb->vb.vb2_buf, VB2_BUF_STATE_DONE); 1452 } 1453 1454 static v4l2_std_id tw5864_get_v4l2_std(enum tw5864_vid_std std) 1455 { 1456 switch (std) { 1457 case STD_NTSC: return V4L2_STD_NTSC_M; 1458 case STD_PAL: return V4L2_STD_PAL_B; 1459 case STD_SECAM: return V4L2_STD_SECAM_B; 1460 case STD_NTSC443: return V4L2_STD_NTSC_443; 1461 case STD_PAL_M: return V4L2_STD_PAL_M; 1462 case STD_PAL_CN: return V4L2_STD_PAL_Nc; 1463 case STD_PAL_60: return V4L2_STD_PAL_60; 1464 case STD_INVALID: return V4L2_STD_UNKNOWN; 1465 } 1466 return 0; 1467 } 1468 1469 static enum tw5864_vid_std tw5864_from_v4l2_std(v4l2_std_id v4l2_std) 1470 { 1471 if (v4l2_std & V4L2_STD_NTSC_M) 1472 return STD_NTSC; 1473 if (v4l2_std & V4L2_STD_PAL_B) 1474 return STD_PAL; 1475 if (v4l2_std & V4L2_STD_SECAM_B) 1476 return STD_SECAM; 1477 if (v4l2_std & V4L2_STD_NTSC_443) 1478 return STD_NTSC443; 1479 if (v4l2_std & V4L2_STD_PAL_M) 1480 return STD_PAL_M; 1481 if (v4l2_std & V4L2_STD_PAL_Nc) 1482 return STD_PAL_CN; 1483 if (v4l2_std & V4L2_STD_PAL_60) 1484 return STD_PAL_60; 1485 1486 return STD_INVALID; 1487 } 1488 1489 static void tw5864_encoder_tables_upload(struct tw5864_dev *dev) 1490 { 1491 int i; 1492 1493 tw_writel(TW5864_VLC_RD, 0x1); 1494 for (i = 0; i < VLC_LOOKUP_TABLE_LEN; i++) { 1495 tw_writel((TW5864_VLC_STREAM_MEM_START + i * 4), 1496 encoder_vlc_lookup_table[i]); 1497 } 1498 tw_writel(TW5864_VLC_RD, 0x0); 1499 1500 for (i = 0; i < QUANTIZATION_TABLE_LEN; i++) { 1501 tw_writel((TW5864_QUAN_TAB + i * 4), 1502 forward_quantization_table[i]); 1503 } 1504 1505 for (i = 0; i < QUANTIZATION_TABLE_LEN; i++) { 1506 tw_writel((TW5864_QUAN_TAB + i * 4), 1507 inverse_quantization_table[i]); 1508 } 1509 } 1510