File indexing completed on 2025-05-11 08:23:44
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #define RTEMS_STATUS_CHECKS_USE_PRINTK
0013
0014 #include <stdlib.h>
0015 #include <stdio.h>
0016 #include <errno.h>
0017 #include <sys/types.h>
0018 #include <rtems.h>
0019 #include <bsp.h>
0020 #include <bsp/irq-generic.h>
0021 #include <rtems/libio.h>
0022 #include <rtems/status-checks.h>
0023 #include <rtems/bspIo.h>
0024 #include "../include/system_conf.h"
0025 #include <bsp/milkymist_video.h>
0026
0027 #define DEVICE_NAME "/dev/video"
0028 #define N_BUFFERS 3
0029 #define FRAME_W 720
0030 #define FRAME_H 288
0031
0032 static bool buffers_locked[N_BUFFERS];
0033 static void *buffers[N_BUFFERS];
0034 static int last_buffer;
0035 static int current_buffer;
0036
0037 static rtems_isr frame_handler(rtems_vector_number n)
0038 {
0039 int remaining_attempts;
0040
0041 lm32_interrupt_ack(1 << MM_IRQ_VIDEOIN);
0042
0043 last_buffer = current_buffer;
0044
0045
0046 remaining_attempts = N_BUFFERS;
0047 do {
0048 current_buffer++;
0049 if(current_buffer == N_BUFFERS)
0050 current_buffer = 0;
0051 remaining_attempts--;
0052 } while(buffers_locked[current_buffer] && (remaining_attempts > 0));
0053
0054 MM_WRITE(MM_BT656_BASE, (unsigned int)buffers[current_buffer]);
0055
0056 if(buffers_locked[current_buffer])
0057 printk("Failed to find unlocked buffer\n");
0058 }
0059
0060 static void i2c_delay(void)
0061 {
0062 unsigned int i;
0063
0064 for(i=0;i<1000;i++) __asm__("nop");
0065 }
0066
0067
0068 static unsigned int i2c_read_bit(void)
0069 {
0070 unsigned int bit;
0071
0072
0073 MM_WRITE(MM_BT656_I2C, 0);
0074 i2c_delay();
0075 MM_WRITE(MM_BT656_I2C, BT656_I2C_SDC);
0076 i2c_delay();
0077 bit = MM_READ(MM_BT656_I2C) & BT656_I2C_SDAIN;
0078 i2c_delay();
0079 MM_WRITE(MM_BT656_I2C, 0);
0080 return bit;
0081 }
0082
0083 static void i2c_write_bit(unsigned int bit)
0084 {
0085 if(bit) {
0086 MM_WRITE(MM_BT656_I2C, BT656_I2C_SDAOE|BT656_I2C_SDAOUT);
0087 } else {
0088 MM_WRITE(MM_BT656_I2C, BT656_I2C_SDAOE);
0089 }
0090 i2c_delay();
0091 MM_WRITE(MM_BT656_I2C, MM_READ(MM_BT656_I2C) | BT656_I2C_SDC);
0092 i2c_delay();
0093 MM_WRITE(MM_BT656_I2C, MM_READ(MM_BT656_I2C) & ~BT656_I2C_SDC);
0094 }
0095
0096 static int i2c_started;
0097
0098 static void i2c_start_cond(void)
0099 {
0100 if(i2c_started) {
0101
0102 MM_WRITE(MM_BT656_I2C, BT656_I2C_SDAOE|BT656_I2C_SDAOUT);
0103 i2c_delay();
0104 MM_WRITE(MM_BT656_I2C, MM_READ(MM_BT656_I2C) | BT656_I2C_SDC);
0105 }
0106
0107 MM_WRITE(MM_BT656_I2C, BT656_I2C_SDAOE|BT656_I2C_SDC);
0108 i2c_delay();
0109 MM_WRITE(MM_BT656_I2C, BT656_I2C_SDAOE);
0110 i2c_started = 1;
0111 }
0112
0113 static void i2c_stop_cond(void)
0114 {
0115
0116 MM_WRITE(MM_BT656_I2C, BT656_I2C_SDAOE);
0117 i2c_delay();
0118
0119 MM_WRITE(MM_BT656_I2C, BT656_I2C_SDAOE|BT656_I2C_SDC);
0120
0121 MM_WRITE(MM_BT656_I2C, BT656_I2C_SDC);
0122 i2c_delay();
0123 i2c_started = 0;
0124 }
0125
0126 static unsigned int i2c_write(unsigned char byte)
0127 {
0128 unsigned int bit;
0129 unsigned int ack;
0130
0131 for(bit = 0; bit < 8; bit++) {
0132 i2c_write_bit(byte & 0x80);
0133 byte <<= 1;
0134 }
0135 ack = !i2c_read_bit();
0136 return ack;
0137 }
0138
0139 static unsigned char i2c_read(int ack)
0140 {
0141 unsigned char byte = 0;
0142 unsigned int bit;
0143
0144 for(bit = 0; bit < 8; bit++) {
0145 byte <<= 1;
0146 byte |= i2c_read_bit();
0147 }
0148 i2c_write_bit(!ack);
0149 return byte;
0150 }
0151
0152 static unsigned char read_reg(unsigned char addr)
0153 {
0154 unsigned char r;
0155
0156 i2c_start_cond();
0157 i2c_write(0x40);
0158 i2c_write(addr);
0159 i2c_start_cond();
0160 i2c_write(0x41);
0161 r = i2c_read(0);
0162 i2c_stop_cond();
0163
0164 return r;
0165 }
0166
0167 static void write_reg(unsigned char addr, unsigned char val)
0168 {
0169 i2c_start_cond();
0170 i2c_write(0x40);
0171 i2c_write(addr);
0172 i2c_write(val);
0173 i2c_stop_cond();
0174 }
0175
0176 static const char vreg_addr[] = {
0177 0x1d, 0xc3, 0xc4
0178 };
0179
0180 static const char vreg_dat[] = {
0181 0x40, 0x05, 0x80
0182 };
0183
0184 rtems_device_driver video_initialize(
0185 rtems_device_major_number major,
0186 rtems_device_minor_number minor,
0187 void *arg
0188 )
0189 {
0190 rtems_status_code sc;
0191 rtems_isr_entry dummy;
0192 int i;
0193
0194 MM_WRITE(MM_BT656_I2C, BT656_I2C_SDC);
0195
0196 sc = rtems_io_register_name(DEVICE_NAME, major, 0);
0197 RTEMS_CHECK_SC(sc, "create video input device");
0198
0199 rtems_interrupt_catch(frame_handler, MM_IRQ_VIDEOIN, &dummy);
0200 bsp_interrupt_vector_enable(MM_IRQ_VIDEOIN);
0201
0202 for(i=0;i<sizeof(vreg_addr);i++)
0203 write_reg(vreg_addr[i], vreg_dat[i]);
0204
0205 return RTEMS_SUCCESSFUL;
0206 }
0207
0208 rtems_device_driver video_open(
0209 rtems_device_major_number major,
0210 rtems_device_minor_number minor,
0211 void *arg
0212 )
0213 {
0214 int i;
0215 int status;
0216
0217 for(i=0;i<N_BUFFERS;i++) {
0218 status = posix_memalign(&buffers[i], 32, 2*FRAME_W*FRAME_H);
0219 if(status != 0) {
0220 i--;
0221 while(i > 0) {
0222 free(buffers[i]);
0223 i--;
0224 }
0225 return RTEMS_UNSATISFIED;
0226 }
0227 }
0228
0229 last_buffer = -1;
0230 current_buffer = 0;
0231
0232 MM_WRITE(MM_BT656_BASE, (unsigned int)buffers[current_buffer]);
0233 MM_WRITE(MM_BT656_FILTERSTATUS, BT656_FILTER_FIELD1);
0234
0235 return RTEMS_SUCCESSFUL;
0236 }
0237
0238 rtems_device_driver video_close(
0239 rtems_device_major_number major,
0240 rtems_device_minor_number minor,
0241 void *arg
0242 )
0243 {
0244 int i;
0245
0246 MM_WRITE(MM_BT656_FILTERSTATUS, 0);
0247 while(MM_READ(MM_BT656_FILTERSTATUS) & BT656_FILTER_INFRAME);
0248 for(i=0;i<N_BUFFERS;i++)
0249 free(buffers[i]);
0250 return RTEMS_SUCCESSFUL;
0251 }
0252
0253 static void invalidate_caches(void)
0254 {
0255 volatile char *flushbase = (char *)FMLBRG_FLUSH_BASE;
0256 int i, offset;
0257
0258 offset = 0;
0259 for (i=0;i<FMLBRG_LINE_COUNT;i++) {
0260 flushbase[offset] = 0;
0261 offset += FMLBRG_LINE_LENGTH;
0262 }
0263 __asm__ volatile(
0264 "wcsr DCC, r0\n"
0265 "nop\n"
0266 );
0267 }
0268
0269 static void set_format(int format)
0270 {
0271 switch(format) {
0272 case VIDEO_FORMAT_CVBS6:
0273 write_reg(0x00, 0x00);
0274 write_reg(0xc3, 0x05);
0275 write_reg(0xc4, 0x80);
0276 break;
0277 case VIDEO_FORMAT_CVBS5:
0278 write_reg(0x00, 0x00);
0279 write_reg(0xc3, 0x0d);
0280 write_reg(0xc4, 0x80);
0281 break;
0282 case VIDEO_FORMAT_CVBS4:
0283 write_reg(0x00, 0x00);
0284 write_reg(0xc3, 0x04);
0285 write_reg(0xc4, 0x80);
0286 break;
0287 case VIDEO_FORMAT_SVIDEO:
0288 write_reg(0x00, 0x06);
0289 write_reg(0xc3, 0xd5);
0290 write_reg(0xc4, 0x80);
0291 break;
0292 case VIDEO_FORMAT_COMPONENT:
0293 write_reg(0x00, 0x09);
0294 write_reg(0xc3, 0x45);
0295 write_reg(0xc4, 0x8d);
0296 break;
0297 }
0298 }
0299
0300 rtems_device_driver video_control(
0301 rtems_device_major_number major,
0302 rtems_device_minor_number minor,
0303 void *arg
0304 )
0305 {
0306 rtems_libio_ioctl_args_t *args = arg;
0307 unsigned int *a = (unsigned int *)args->buffer;
0308 rtems_status_code sc;
0309
0310 switch (args->command) {
0311 case VIDEO_BUFFER_LOCK:
0312 if (last_buffer == -1) {
0313 *a = 0;
0314 } else {
0315 bsp_interrupt_vector_disable(MM_IRQ_VIDEOIN);
0316 if(*a) invalidate_caches();
0317 *a = (unsigned int)buffers[last_buffer];
0318 buffers_locked[last_buffer] = true;
0319 bsp_interrupt_vector_enable(MM_IRQ_VIDEOIN);
0320 }
0321 sc = RTEMS_SUCCESSFUL;
0322 break;
0323 case VIDEO_BUFFER_UNLOCK: {
0324 int i;
0325 for(i=0;i<N_BUFFERS;i++) {
0326 if ((unsigned int)buffers[i] == (unsigned int)a) {
0327 buffers_locked[i] = false;
0328 break;
0329 }
0330 }
0331 sc = RTEMS_SUCCESSFUL;
0332 break;
0333 }
0334
0335 case VIDEO_SET_BRIGHTNESS:
0336 write_reg(0x0a, (unsigned int)a);
0337 sc = RTEMS_SUCCESSFUL;
0338 break;
0339 case VIDEO_GET_BRIGHTNESS:
0340 *a = read_reg(0x0a);
0341 sc = RTEMS_SUCCESSFUL;
0342 break;
0343 case VIDEO_SET_CONTRAST:
0344 write_reg(0x08, (unsigned int)a);
0345 sc = RTEMS_SUCCESSFUL;
0346 break;
0347 case VIDEO_GET_CONTRAST:
0348 *a = read_reg(0x08);
0349 sc = RTEMS_SUCCESSFUL;
0350 break;
0351 case VIDEO_SET_HUE:
0352 write_reg(0x0b, (unsigned int)a);
0353 sc = RTEMS_SUCCESSFUL;
0354 break;
0355 case VIDEO_GET_HUE:
0356 *a = read_reg(0x0b);
0357 sc = RTEMS_SUCCESSFUL;
0358 break;
0359
0360 case VIDEO_GET_SIGNAL:
0361 *a = read_reg(0x10);
0362 sc = RTEMS_SUCCESSFUL;
0363 break;
0364
0365 case VIDEO_SET_REGISTER:
0366 write_reg(((unsigned int)a & 0xffff0000) >> 16,
0367 (unsigned int)a & 0x0000ffff);
0368 sc = RTEMS_SUCCESSFUL;
0369 break;
0370 case VIDEO_GET_REGISTER:
0371 *a = read_reg(*a);
0372 sc = RTEMS_SUCCESSFUL;
0373 break;
0374
0375 case VIDEO_SET_FORMAT:
0376 set_format((int)a);
0377 sc = RTEMS_SUCCESSFUL;
0378 break;
0379
0380 default:
0381 sc = RTEMS_UNSATISFIED;
0382 break;
0383 }
0384
0385 if (sc == RTEMS_SUCCESSFUL)
0386 args->ioctl_return = 0;
0387 else
0388 args->ioctl_return = -1;
0389
0390 return sc;
0391 }