Loading src/drivers/elphel/circbuf.c +146 −13 Original line number Diff line number Diff line Loading @@ -279,12 +279,27 @@ void dump_interframe_params(struct interframe_params_t *params, int offset) */ unsigned long get_image_length(int byte_offset, unsigned int chn, int *last_chunk_offset) { unsigned int offset; unsigned long len32; int last_image_chunk = byte_offset - OFFSET_X40; int last_image_chunk = X393_BUFFSUB(byte_offset, OFFSET_X40); if (last_image_chunk < 0) last_image_chunk += CCAM_DMA_SIZE; len32 = circbuf_priv[chn].buf_ptr[BYTE2DW(last_image_chunk + (CHUNK_SIZE - CCAM_MMAP_META_LENGTH))]; // if (last_image_chunk < 0) // last_image_chunk += CCAM_DMA_SIZE; // len32 = circbuf_priv[chn].buf_ptr[BYTE2DW(last_image_chunk + (CHUNK_SIZE - CCAM_MMAP_META_LENGTH))]; offset = last_image_chunk + (CHUNK_SIZE - CCAM_MMAP_META_LENGTH); len32 = circbuf_priv[chn].buf_ptr[BYTE2DW(offset)]; if ((len32 & MARKER_FF) != MARKER_FF) { printk(KERN_DEBUG "failed to get 0xff marker at offset 0x%x\n", offset); byte_offset = X393_BUFFSUB(byte_offset, 0x20); last_image_chunk = X393_BUFFSUB(byte_offset, OFFSET_X40); offset = last_image_chunk + (CHUNK_SIZE - CCAM_MMAP_META_LENGTH); len32 = circbuf_priv[chn].buf_ptr[BYTE2DW(offset)]; if ((len32 & MARKER_FF) != MARKER_FF) { printk(KERN_DEBUG "failed to get 0xff marker at CORRECTED offset 0x%x\n", offset); return 0; } } dev_dbg(g_dev_ptr, "got len32 = 0x%lx at 0x%x\n", len32, last_image_chunk + (CHUNK_SIZE - CCAM_MMAP_META_LENGTH)); Loading @@ -301,6 +316,7 @@ unsigned long get_image_length(int byte_offset, unsigned int chn, int *last_chun * frame header before \e rp and will point to its parameters * @param[in] chn specify compressor channel number which pointer should be checked * @return 0 if the pointer is for the frame yet to be acquired, 1 if there is a valid frame at this address, * 2 if file pointer should be advanced by 32 bytes, * -1 if there is no frame at this index, -2 if the pointer is not 32-bytes aligned * sets *fpp to the frame header, including signature and length */ Loading @@ -311,7 +327,7 @@ int circbuf_valid_ptr(int rp, struct interframe_params_t **fpp, unsigned int chn unsigned int usec; int wp = camseq_get_jpeg_wp(chn); unsigned int len32 = get_image_length(DW2BYTE(wp), chn, &last_image_chunk); struct interframe_params_t *fp; struct interframe_params_t *fp, *fp_off; if (rp & 0x1f) { // rp is not 32-bytes aligned Loading @@ -328,13 +344,33 @@ int circbuf_valid_ptr(int rp, struct interframe_params_t **fpp, unsigned int chn return 0; if (fp->signffff != MARKER_FFFF) { dev_dbg(g_dev_ptr, "interframe signature is overwritten\n"); dev_dbg(g_dev_ptr, "interframe signature is overwritten, signffff = 0x%x\n", fp->signffff); fp_off = (struct interframe_params_t *) &circbuf_priv[chn].buf_ptr[BYTE2DW(rp)]; if (fp_off->signffff != MARKER_FFFF) { dev_dbg(g_dev_ptr, "interframe signature is overwritten at CORRECTED offset, signffff = 0x%x\n", fp_off->signffff); return -1; } else { dev_dbg(g_dev_ptr, "interframe pointer is advanced by 0x20\n"); *fpp = fp_off; dump_interframe_params(fp_off, rp); return 2; } } return 1; } /** * @brief Get image start offset pointed by its last data chunk * @param[in] last_chunk_offset offset of the last image data chunk * @param[in] len32 length of image * @return image start offset */ inline int get_image_start(int last_chunk_offset, unsigned int len32) { return X393_BUFFSUB(last_chunk_offset + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32); } /** * @brief Reposition read/write file offset * Loading Loading @@ -380,6 +416,62 @@ int circbuf_valid_ptr(int rp, struct interframe_params_t **fpp, unsigned int chn * @param[in] orig origin * @return current file pointer position if operation was successful and error code otherwise */ /* debug code follows */ void stop_compressor(unsigned int chn) { x393_cmprs_mode_t mode; mode.run = 1; mode.run_set = 1; x393_cmprs_control_reg(mode, chn); } void dump_state(unsigned int chn) { int img_start, last_image_chunk; int len32; int prev_ptr, prevprev_ptr; int read_ptr = DW2BYTE(camseq_get_jpeg_wp(chn)); unsigned int nf, nz; struct interframe_params_t *fp; nf = 0; nz = 1; printk(KERN_DEBUG "=== start of state dump, chn = %d ===\n", chn); printk(KERN_DEBUG "hardware pointer at 0x%x\n", read_ptr); // move to the beginning of last frame len32 = get_image_length(read_ptr, chn, &last_image_chunk); if ((len32 & MARKER_FF) != MARKER_FF) { printk(KERN_DEBUG "last acquired frame at location 0x%x is damaged\n", read_ptr); return; } len32 &= FRAME_LENGTH_MASK; //img_start = X393_BUFFSUB(last_image_chunk + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32); img_start = get_image_start(last_image_chunk, len32); read_ptr = img_start; // move back in history while ((circbuf_valid_ptr(read_ptr, &fp, chn) >= 0) && (nz >= 0)) { printk(KERN_DEBUG "analyzing frame starting at 0x%x\n", read_ptr); //printk(KERN_DEBUG "mem dump of 0x40 bytes at (pointer - 0x20) = 0x%x:\n", read_ptr - OFFSET_X40 / 2); //print_hex_dump_bytes("\t\t", DUMP_PREFIX_OFFSET, &circbuf_priv[chn].buf_ptr[BYTE2DW(read_ptr - OFFSET_X40 / 2)], OFFSET_X40); nf++; prevprev_ptr = prev_ptr; prev_ptr = read_ptr; len32 = get_image_length(read_ptr, chn, &last_image_chunk); if ((len32 & MARKER_FF) != MARKER_FF) { printk(KERN_DEBUG "\t\tno image before 0x%x\n", read_ptr); break; } len32 &= FRAME_LENGTH_MASK; //printk(KERN_DEBUG "\t\tgot len32 = 0x%x", len32); //img_start = X393_BUFFSUB(last_image_chunk + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32); img_start = get_image_start(last_image_chunk, len32); read_ptr = img_start; if (read_ptr > prev_ptr) nz--; } printk(KERN_DEBUG "=== end of state dump, %d frame(s) analyzed ===\n", nf); } /* end of debug code */ loff_t circbuf_lseek(struct file *file, loff_t offset, int orig) { unsigned int len32 = 0; Loading Loading @@ -418,6 +510,18 @@ loff_t circbuf_lseek(struct file *file, loff_t offset, int orig) case LSEEK_CIRC_USED: if ((fvld = circbuf_valid_ptr(file->f_pos, &fp, chn)) < 0) return -EINVAL; // no frames at the specified location break; /* debug code follows */ case LSEEK_CIRC_STOP_COMPRESSOR: { int s; dev_dbg(g_dev_ptr, "stopping all compressors, current channel %d, fvld = %d, file->f_pos = 0x%llx\n", chn, fvld, file->f_pos); for (s = 0; s < IMAGE_CHN_NUM; s++) stop_compressor(s); dump_state(chn); } break; /* end of debug code */ } switch (offset) { case LSEEK_CIRC_FREE: Loading Loading @@ -448,7 +552,8 @@ loff_t circbuf_lseek(struct file *file, loff_t offset, int orig) return -EOVERFLOW; } len32 &= FRAME_LENGTH_MASK; img_start = X393_BUFFSUB(last_image_chunk + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32); //img_start = X393_BUFFSUB(last_image_chunk + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32); img_start = get_image_start(last_image_chunk, len32); dev_dbg(g_dev_ptr, "calculated start address = 0x%x, length = 0x%x\n", img_start, len32); if (circbuf_valid_ptr(img_start, &fp, chn) < 0) return -EOVERFLOW; Loading @@ -470,7 +575,8 @@ loff_t circbuf_lseek(struct file *file, loff_t offset, int orig) return -EOVERFLOW; } len32 &= FRAME_LENGTH_MASK; img_start = X393_BUFFSUB(last_image_chunk + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32); //img_start = X393_BUFFSUB(last_image_chunk + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32); img_start = get_image_start(last_image_chunk, len32); dev_dbg(g_dev_ptr, "LSEEK_CIRC_PREV: calculated start address = 0x%x, length = 0x%x\n", img_start, len32); // move file pointer only if previous frame valid Loading @@ -481,8 +587,11 @@ loff_t circbuf_lseek(struct file *file, loff_t offset, int orig) break; case LSEEK_CIRC_NEXT: dev_dbg(g_dev_ptr, "LSEEK_CIRC_NEXT: file->f_pos = 0x%lx, fvld = %d, fp->len32 = 0x%lx\n", file->f_pos, fvld, fp->frame_length); if (fvld <= 0) if (fvld <= 0) { return -EOVERFLOW; //! no frames after current } else if (fvld == 2) { file->f_pos += CHUNK_SIZE; } // calculate the full length of current frame and advance file pointer by this value padded_frame = fp->frame_length + INSERTED_BYTES(fp->frame_length) + CHUNK_SIZE + CCAM_MMAP_META; file->f_pos = X393_BUFFADD(file->f_pos, padded_frame); // do it even if the next frame does not yet exist Loading @@ -507,7 +616,8 @@ loff_t circbuf_lseek(struct file *file, loff_t offset, int orig) if ((len32 & MARKER_FF) != MARKER_FF ) break; //! no frames before rp (==prev_p) //! move rp to the previous frame len32 &= FRAME_LENGTH_MASK; img_start = X393_BUFFSUB(last_image_chunk + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32); //img_start = X393_BUFFSUB(last_image_chunk + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32); img_start = get_image_start(last_image_chunk, len32); dev_dbg(g_dev_ptr, "LSEEK_CIRC_FIRST or LSEEK_CIRC_SCND: calculated start address = 0x%x, length = 0x%x\n", img_start, len32); rp = BYTE2DW(img_start); if (rp > prev_p) nz--; // rolled through zero - make sure we'll not stuck in this loop forever Loading Loading @@ -562,12 +672,17 @@ loff_t circbuf_lseek(struct file *file, loff_t offset, int orig) * @param[in] off offset * @return number of bytes read form \e buf */ unsigned short circbuf_quality = 100; ssize_t circbuf_write(struct file *file, const char *buf, size_t count, loff_t *off) { unsigned long p; unsigned int minor = MINOR(file->f_inode->i_rdev); unsigned int chn = minor_to_chn(minor, NULL); dev_dbg(g_dev_ptr, "minor = 0x%x, count = 0x%x, off = 0x%lx", minor, count, off); int i; int ret; long val; char *buf_copy = (char *)buf; dev_dbg(g_dev_ptr, "minor = 0x%x, count = 0x%x, off = 0x%llx", minor, count, off); /* debug code follows*/ switch (buf[0] - 0x30) { Loading @@ -577,6 +692,24 @@ ssize_t circbuf_write(struct file *file, const char *buf, size_t count, loff_t * case 1: camera_interrupts(1); break; case 3: buf_copy[count - 1] = 0; ret = kstrtol(&buf_copy[2], 10, &val); dev_dbg(g_dev_ptr, "ret: %d, buf[2]: %s\n", ret, &buf_copy[2]); if (count > 2 && ret == 0) { if (val > 0 && val <= 100) { circbuf_quality = val; dev_dbg(g_dev_ptr, "set quality %d\n", circbuf_quality); } } else { dev_dbg(g_dev_ptr, "error, unable to process quality parameter\n"); } break; case 4: for (i = 0; i < IMAGE_CHN_NUM; i++) stop_compressor(i); dump_state(chn); break; } /* debug code end */ Loading src/drivers/elphel/circbuf.h +4 −0 Original line number Diff line number Diff line Loading @@ -42,4 +42,8 @@ struct circbuf_priv_t { }; extern struct circbuf_priv_t *circbuf_priv_ptr; /* debug code follows */ extern unsigned short circbuf_quality; /* end of debug code */ #endif /* _CIRCBUF_H */ src/drivers/elphel/sensor_common.c +50 −4 Original line number Diff line number Diff line Loading @@ -41,6 +41,8 @@ //#include <linux/of.h> //#include <linux/of_device.h> #include <asm/outercache.h> #include <asm/cacheflush.h> //#include <asm/system.h> //#include <asm/byteorder.h> // endians Loading Loading @@ -114,6 +116,10 @@ struct image_acq_pd_t { int minor; struct jpeg_ptr_t jpeg_ptr[IMAGE_CHN_NUM]; }; /* debug code follows */ // jpeg_hw_wp is equal to hardware pointer, jpeg_wp will lag from jpeg_hw_wp by one frame static volatile int jpeg_hw_wp[IMAGE_CHN_NUM]; /* end of debug code */ static struct image_acq_pd_t image_acq_priv; Loading Loading @@ -242,10 +248,12 @@ DECLARE_TASKLET(tasklet_fpga, tasklet_fpga_function, 0); /// 0 - no arguments fo */ static inline int updateIRQJPEG_wp(struct jpeg_ptr_t *jptr) { phys_addr_t phys_addr; void *virt_addr; int xferred; /// number of 32-byte chunks transferred since compressor was reset x393_afimux_status_t stat = x393_afimux0_status(jptr->chn_num); //int circbuf_size = get_globalParam(G_CIRCBUFSIZE) >> 2; int circbuf_size = get_globalParam(G_CIRCBUFSIZE); int circbuf_size = get_globalParam(G_CIRCBUFSIZE) >> 2; //int circbuf_size = get_globalParam(G_CIRCBUFSIZE); xferred = stat.offset256 - jptr->fpga_cntr_prev; if (xferred == 0) Loading @@ -253,8 +261,27 @@ static inline int updateIRQJPEG_wp(struct jpeg_ptr_t *jptr) jptr->flags |= SENS_FLAG_IRQ; jptr->fpga_cntr_prev = stat.offset256; // if (xferred < 0) // xferred += (1 << 26); // increment in 32 bit words jptr->jpeg_wp += (xferred << 3); // jptr->jpeg_wp += (xferred << 3); jptr->jpeg_wp = (stat.offset256 << 3); // if (jptr->jpeg_wp > circbuf_size) // jptr->jpeg_wp -= circbuf_size; // invalidate CPU L1 and L2 caches phys_addr = circbuf_priv_ptr[jptr->chn_num].phys_addr + DW2BYTE(jptr->jpeg_wp) - CHUNK_SIZE; virt_addr = circbuf_priv_ptr[jptr->chn_num].buf_ptr + jptr->jpeg_wp - INTERFRAME_PARAMS_SZ; outer_inv_range(phys_addr, phys_addr + (CHUNK_SIZE - 1)); __cpuc_flush_dcache_area(virt_addr, CHUNK_SIZE); // printk(KERN_DEBUG "this channel start address: phys_addr = 0x%x; buf_ptr = 0x%x", // circbuf_priv_ptr[jptr->chn_num].phys_addr, circbuf_priv_ptr[jptr->chn_num].buf_ptr); // printk(KERN_DEBUG "invalidate cache for channel %d: phys_addr = 0x%x; virt_addr = 0x%x\n", // jptr->chn_num, phys_addr, virt_addr); // printk(KERN_DEBUG "\t\tcurrent parameters: offset256 = 0x%x, fpga_prev_cntr = 0x%x, jpeg_wp = 0x%x, xferred = 0x%x\n", // stat.offset256, jptr->fpga_cntr_prev, jptr->jpeg_wp, xferred); return 1; } Loading Loading @@ -289,7 +316,8 @@ inline static void set_default_interframe(struct interframe_params_t *params) params->width = 2592; params->byrshift = 3; params->color = 0; params->quality2 = 100; params->quality2 = circbuf_quality; //params->quality2 = 100; } /** Loading @@ -313,6 +341,8 @@ inline struct interframe_params_t* updateIRQ_interframe(struct jpeg_ptr_t *jptr) // set_globalParam (0x306,get_globalParam (0x306)+1); //#endif dma_addr_t phys_addr; void *virt_addr; struct interframe_params_t *interframe; int len_offset = X393_BUFFSUB(jptr->jpeg_wp, INTERFRAME_PARAMS_SZ + 1); int jpeg_len = circbuf_priv_ptr[jptr->chn_num].buf_ptr[len_offset] & FRAME_LENGTH_MASK; Loading @@ -328,6 +358,19 @@ inline struct interframe_params_t* updateIRQ_interframe(struct jpeg_ptr_t *jptr) set_globalParam(G_FRAME_SIZE, jpeg_len); // invalidate CPU L1 and L2 caches phys_addr = circbuf_priv_ptr[jptr->chn_num].phys_addr + DW2BYTE(frame_params_offset); //virt_addr = circbuf_priv_ptr[jptr->chn_num].buf_ptr + frame_params_offset; virt_addr = interframe; __cpuc_flush_dcache_area(virt_addr, CHUNK_SIZE); outer_inv_range(phys_addr, phys_addr + (CHUNK_SIZE - 1)); if (jptr->chn_num == 0) { printk(KERN_DEBUG "this channel start address: phys_addr = 0x%x; buf_ptr = 0x%x", circbuf_priv_ptr[jptr->chn_num].phys_addr, circbuf_priv_ptr[jptr->chn_num].buf_ptr); printk(KERN_DEBUG "invalidate cache for channel %d: phys_addr = 0x%x; virt_addr = 0x%x\n", jptr->chn_num, phys_addr, virt_addr); } return interframe; } Loading Loading @@ -644,6 +687,9 @@ void reset_compressor(unsigned int chn) image_acq_priv.jpeg_ptr[chn].jpeg_rp = 0; image_acq_priv.jpeg_ptr[chn].fpga_cntr_prev = 0; image_acq_priv.jpeg_ptr[chn].flags = 0; /* debug code follows */ jpeg_hw_wp[chn] = 0; /* debug code end */ //update_irq_circbuf(jptr); local_irq_restore(flags); } Loading src/include/elphel/c313a.h +1 −0 Original line number Diff line number Diff line Loading @@ -1361,6 +1361,7 @@ struct p_names_t { #define LSEEK_CIRC_WAIT 11 #define LSEEK_CIRC_FREE 12 #define LSEEK_CIRC_USED 13 #define LSEEK_CIRC_STOP_COMPRESSOR 14 #define LSEEK_HUFFMAN_DC0 1 #define LSEEK_HUFFMAN_AC0 2 Loading Loading
src/drivers/elphel/circbuf.c +146 −13 Original line number Diff line number Diff line Loading @@ -279,12 +279,27 @@ void dump_interframe_params(struct interframe_params_t *params, int offset) */ unsigned long get_image_length(int byte_offset, unsigned int chn, int *last_chunk_offset) { unsigned int offset; unsigned long len32; int last_image_chunk = byte_offset - OFFSET_X40; int last_image_chunk = X393_BUFFSUB(byte_offset, OFFSET_X40); if (last_image_chunk < 0) last_image_chunk += CCAM_DMA_SIZE; len32 = circbuf_priv[chn].buf_ptr[BYTE2DW(last_image_chunk + (CHUNK_SIZE - CCAM_MMAP_META_LENGTH))]; // if (last_image_chunk < 0) // last_image_chunk += CCAM_DMA_SIZE; // len32 = circbuf_priv[chn].buf_ptr[BYTE2DW(last_image_chunk + (CHUNK_SIZE - CCAM_MMAP_META_LENGTH))]; offset = last_image_chunk + (CHUNK_SIZE - CCAM_MMAP_META_LENGTH); len32 = circbuf_priv[chn].buf_ptr[BYTE2DW(offset)]; if ((len32 & MARKER_FF) != MARKER_FF) { printk(KERN_DEBUG "failed to get 0xff marker at offset 0x%x\n", offset); byte_offset = X393_BUFFSUB(byte_offset, 0x20); last_image_chunk = X393_BUFFSUB(byte_offset, OFFSET_X40); offset = last_image_chunk + (CHUNK_SIZE - CCAM_MMAP_META_LENGTH); len32 = circbuf_priv[chn].buf_ptr[BYTE2DW(offset)]; if ((len32 & MARKER_FF) != MARKER_FF) { printk(KERN_DEBUG "failed to get 0xff marker at CORRECTED offset 0x%x\n", offset); return 0; } } dev_dbg(g_dev_ptr, "got len32 = 0x%lx at 0x%x\n", len32, last_image_chunk + (CHUNK_SIZE - CCAM_MMAP_META_LENGTH)); Loading @@ -301,6 +316,7 @@ unsigned long get_image_length(int byte_offset, unsigned int chn, int *last_chun * frame header before \e rp and will point to its parameters * @param[in] chn specify compressor channel number which pointer should be checked * @return 0 if the pointer is for the frame yet to be acquired, 1 if there is a valid frame at this address, * 2 if file pointer should be advanced by 32 bytes, * -1 if there is no frame at this index, -2 if the pointer is not 32-bytes aligned * sets *fpp to the frame header, including signature and length */ Loading @@ -311,7 +327,7 @@ int circbuf_valid_ptr(int rp, struct interframe_params_t **fpp, unsigned int chn unsigned int usec; int wp = camseq_get_jpeg_wp(chn); unsigned int len32 = get_image_length(DW2BYTE(wp), chn, &last_image_chunk); struct interframe_params_t *fp; struct interframe_params_t *fp, *fp_off; if (rp & 0x1f) { // rp is not 32-bytes aligned Loading @@ -328,13 +344,33 @@ int circbuf_valid_ptr(int rp, struct interframe_params_t **fpp, unsigned int chn return 0; if (fp->signffff != MARKER_FFFF) { dev_dbg(g_dev_ptr, "interframe signature is overwritten\n"); dev_dbg(g_dev_ptr, "interframe signature is overwritten, signffff = 0x%x\n", fp->signffff); fp_off = (struct interframe_params_t *) &circbuf_priv[chn].buf_ptr[BYTE2DW(rp)]; if (fp_off->signffff != MARKER_FFFF) { dev_dbg(g_dev_ptr, "interframe signature is overwritten at CORRECTED offset, signffff = 0x%x\n", fp_off->signffff); return -1; } else { dev_dbg(g_dev_ptr, "interframe pointer is advanced by 0x20\n"); *fpp = fp_off; dump_interframe_params(fp_off, rp); return 2; } } return 1; } /** * @brief Get image start offset pointed by its last data chunk * @param[in] last_chunk_offset offset of the last image data chunk * @param[in] len32 length of image * @return image start offset */ inline int get_image_start(int last_chunk_offset, unsigned int len32) { return X393_BUFFSUB(last_chunk_offset + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32); } /** * @brief Reposition read/write file offset * Loading Loading @@ -380,6 +416,62 @@ int circbuf_valid_ptr(int rp, struct interframe_params_t **fpp, unsigned int chn * @param[in] orig origin * @return current file pointer position if operation was successful and error code otherwise */ /* debug code follows */ void stop_compressor(unsigned int chn) { x393_cmprs_mode_t mode; mode.run = 1; mode.run_set = 1; x393_cmprs_control_reg(mode, chn); } void dump_state(unsigned int chn) { int img_start, last_image_chunk; int len32; int prev_ptr, prevprev_ptr; int read_ptr = DW2BYTE(camseq_get_jpeg_wp(chn)); unsigned int nf, nz; struct interframe_params_t *fp; nf = 0; nz = 1; printk(KERN_DEBUG "=== start of state dump, chn = %d ===\n", chn); printk(KERN_DEBUG "hardware pointer at 0x%x\n", read_ptr); // move to the beginning of last frame len32 = get_image_length(read_ptr, chn, &last_image_chunk); if ((len32 & MARKER_FF) != MARKER_FF) { printk(KERN_DEBUG "last acquired frame at location 0x%x is damaged\n", read_ptr); return; } len32 &= FRAME_LENGTH_MASK; //img_start = X393_BUFFSUB(last_image_chunk + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32); img_start = get_image_start(last_image_chunk, len32); read_ptr = img_start; // move back in history while ((circbuf_valid_ptr(read_ptr, &fp, chn) >= 0) && (nz >= 0)) { printk(KERN_DEBUG "analyzing frame starting at 0x%x\n", read_ptr); //printk(KERN_DEBUG "mem dump of 0x40 bytes at (pointer - 0x20) = 0x%x:\n", read_ptr - OFFSET_X40 / 2); //print_hex_dump_bytes("\t\t", DUMP_PREFIX_OFFSET, &circbuf_priv[chn].buf_ptr[BYTE2DW(read_ptr - OFFSET_X40 / 2)], OFFSET_X40); nf++; prevprev_ptr = prev_ptr; prev_ptr = read_ptr; len32 = get_image_length(read_ptr, chn, &last_image_chunk); if ((len32 & MARKER_FF) != MARKER_FF) { printk(KERN_DEBUG "\t\tno image before 0x%x\n", read_ptr); break; } len32 &= FRAME_LENGTH_MASK; //printk(KERN_DEBUG "\t\tgot len32 = 0x%x", len32); //img_start = X393_BUFFSUB(last_image_chunk + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32); img_start = get_image_start(last_image_chunk, len32); read_ptr = img_start; if (read_ptr > prev_ptr) nz--; } printk(KERN_DEBUG "=== end of state dump, %d frame(s) analyzed ===\n", nf); } /* end of debug code */ loff_t circbuf_lseek(struct file *file, loff_t offset, int orig) { unsigned int len32 = 0; Loading Loading @@ -418,6 +510,18 @@ loff_t circbuf_lseek(struct file *file, loff_t offset, int orig) case LSEEK_CIRC_USED: if ((fvld = circbuf_valid_ptr(file->f_pos, &fp, chn)) < 0) return -EINVAL; // no frames at the specified location break; /* debug code follows */ case LSEEK_CIRC_STOP_COMPRESSOR: { int s; dev_dbg(g_dev_ptr, "stopping all compressors, current channel %d, fvld = %d, file->f_pos = 0x%llx\n", chn, fvld, file->f_pos); for (s = 0; s < IMAGE_CHN_NUM; s++) stop_compressor(s); dump_state(chn); } break; /* end of debug code */ } switch (offset) { case LSEEK_CIRC_FREE: Loading Loading @@ -448,7 +552,8 @@ loff_t circbuf_lseek(struct file *file, loff_t offset, int orig) return -EOVERFLOW; } len32 &= FRAME_LENGTH_MASK; img_start = X393_BUFFSUB(last_image_chunk + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32); //img_start = X393_BUFFSUB(last_image_chunk + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32); img_start = get_image_start(last_image_chunk, len32); dev_dbg(g_dev_ptr, "calculated start address = 0x%x, length = 0x%x\n", img_start, len32); if (circbuf_valid_ptr(img_start, &fp, chn) < 0) return -EOVERFLOW; Loading @@ -470,7 +575,8 @@ loff_t circbuf_lseek(struct file *file, loff_t offset, int orig) return -EOVERFLOW; } len32 &= FRAME_LENGTH_MASK; img_start = X393_BUFFSUB(last_image_chunk + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32); //img_start = X393_BUFFSUB(last_image_chunk + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32); img_start = get_image_start(last_image_chunk, len32); dev_dbg(g_dev_ptr, "LSEEK_CIRC_PREV: calculated start address = 0x%x, length = 0x%x\n", img_start, len32); // move file pointer only if previous frame valid Loading @@ -481,8 +587,11 @@ loff_t circbuf_lseek(struct file *file, loff_t offset, int orig) break; case LSEEK_CIRC_NEXT: dev_dbg(g_dev_ptr, "LSEEK_CIRC_NEXT: file->f_pos = 0x%lx, fvld = %d, fp->len32 = 0x%lx\n", file->f_pos, fvld, fp->frame_length); if (fvld <= 0) if (fvld <= 0) { return -EOVERFLOW; //! no frames after current } else if (fvld == 2) { file->f_pos += CHUNK_SIZE; } // calculate the full length of current frame and advance file pointer by this value padded_frame = fp->frame_length + INSERTED_BYTES(fp->frame_length) + CHUNK_SIZE + CCAM_MMAP_META; file->f_pos = X393_BUFFADD(file->f_pos, padded_frame); // do it even if the next frame does not yet exist Loading @@ -507,7 +616,8 @@ loff_t circbuf_lseek(struct file *file, loff_t offset, int orig) if ((len32 & MARKER_FF) != MARKER_FF ) break; //! no frames before rp (==prev_p) //! move rp to the previous frame len32 &= FRAME_LENGTH_MASK; img_start = X393_BUFFSUB(last_image_chunk + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32); //img_start = X393_BUFFSUB(last_image_chunk + CHUNK_SIZE - INSERTED_BYTES(len32) - CCAM_MMAP_META, len32); img_start = get_image_start(last_image_chunk, len32); dev_dbg(g_dev_ptr, "LSEEK_CIRC_FIRST or LSEEK_CIRC_SCND: calculated start address = 0x%x, length = 0x%x\n", img_start, len32); rp = BYTE2DW(img_start); if (rp > prev_p) nz--; // rolled through zero - make sure we'll not stuck in this loop forever Loading Loading @@ -562,12 +672,17 @@ loff_t circbuf_lseek(struct file *file, loff_t offset, int orig) * @param[in] off offset * @return number of bytes read form \e buf */ unsigned short circbuf_quality = 100; ssize_t circbuf_write(struct file *file, const char *buf, size_t count, loff_t *off) { unsigned long p; unsigned int minor = MINOR(file->f_inode->i_rdev); unsigned int chn = minor_to_chn(minor, NULL); dev_dbg(g_dev_ptr, "minor = 0x%x, count = 0x%x, off = 0x%lx", minor, count, off); int i; int ret; long val; char *buf_copy = (char *)buf; dev_dbg(g_dev_ptr, "minor = 0x%x, count = 0x%x, off = 0x%llx", minor, count, off); /* debug code follows*/ switch (buf[0] - 0x30) { Loading @@ -577,6 +692,24 @@ ssize_t circbuf_write(struct file *file, const char *buf, size_t count, loff_t * case 1: camera_interrupts(1); break; case 3: buf_copy[count - 1] = 0; ret = kstrtol(&buf_copy[2], 10, &val); dev_dbg(g_dev_ptr, "ret: %d, buf[2]: %s\n", ret, &buf_copy[2]); if (count > 2 && ret == 0) { if (val > 0 && val <= 100) { circbuf_quality = val; dev_dbg(g_dev_ptr, "set quality %d\n", circbuf_quality); } } else { dev_dbg(g_dev_ptr, "error, unable to process quality parameter\n"); } break; case 4: for (i = 0; i < IMAGE_CHN_NUM; i++) stop_compressor(i); dump_state(chn); break; } /* debug code end */ Loading
src/drivers/elphel/circbuf.h +4 −0 Original line number Diff line number Diff line Loading @@ -42,4 +42,8 @@ struct circbuf_priv_t { }; extern struct circbuf_priv_t *circbuf_priv_ptr; /* debug code follows */ extern unsigned short circbuf_quality; /* end of debug code */ #endif /* _CIRCBUF_H */
src/drivers/elphel/sensor_common.c +50 −4 Original line number Diff line number Diff line Loading @@ -41,6 +41,8 @@ //#include <linux/of.h> //#include <linux/of_device.h> #include <asm/outercache.h> #include <asm/cacheflush.h> //#include <asm/system.h> //#include <asm/byteorder.h> // endians Loading Loading @@ -114,6 +116,10 @@ struct image_acq_pd_t { int minor; struct jpeg_ptr_t jpeg_ptr[IMAGE_CHN_NUM]; }; /* debug code follows */ // jpeg_hw_wp is equal to hardware pointer, jpeg_wp will lag from jpeg_hw_wp by one frame static volatile int jpeg_hw_wp[IMAGE_CHN_NUM]; /* end of debug code */ static struct image_acq_pd_t image_acq_priv; Loading Loading @@ -242,10 +248,12 @@ DECLARE_TASKLET(tasklet_fpga, tasklet_fpga_function, 0); /// 0 - no arguments fo */ static inline int updateIRQJPEG_wp(struct jpeg_ptr_t *jptr) { phys_addr_t phys_addr; void *virt_addr; int xferred; /// number of 32-byte chunks transferred since compressor was reset x393_afimux_status_t stat = x393_afimux0_status(jptr->chn_num); //int circbuf_size = get_globalParam(G_CIRCBUFSIZE) >> 2; int circbuf_size = get_globalParam(G_CIRCBUFSIZE); int circbuf_size = get_globalParam(G_CIRCBUFSIZE) >> 2; //int circbuf_size = get_globalParam(G_CIRCBUFSIZE); xferred = stat.offset256 - jptr->fpga_cntr_prev; if (xferred == 0) Loading @@ -253,8 +261,27 @@ static inline int updateIRQJPEG_wp(struct jpeg_ptr_t *jptr) jptr->flags |= SENS_FLAG_IRQ; jptr->fpga_cntr_prev = stat.offset256; // if (xferred < 0) // xferred += (1 << 26); // increment in 32 bit words jptr->jpeg_wp += (xferred << 3); // jptr->jpeg_wp += (xferred << 3); jptr->jpeg_wp = (stat.offset256 << 3); // if (jptr->jpeg_wp > circbuf_size) // jptr->jpeg_wp -= circbuf_size; // invalidate CPU L1 and L2 caches phys_addr = circbuf_priv_ptr[jptr->chn_num].phys_addr + DW2BYTE(jptr->jpeg_wp) - CHUNK_SIZE; virt_addr = circbuf_priv_ptr[jptr->chn_num].buf_ptr + jptr->jpeg_wp - INTERFRAME_PARAMS_SZ; outer_inv_range(phys_addr, phys_addr + (CHUNK_SIZE - 1)); __cpuc_flush_dcache_area(virt_addr, CHUNK_SIZE); // printk(KERN_DEBUG "this channel start address: phys_addr = 0x%x; buf_ptr = 0x%x", // circbuf_priv_ptr[jptr->chn_num].phys_addr, circbuf_priv_ptr[jptr->chn_num].buf_ptr); // printk(KERN_DEBUG "invalidate cache for channel %d: phys_addr = 0x%x; virt_addr = 0x%x\n", // jptr->chn_num, phys_addr, virt_addr); // printk(KERN_DEBUG "\t\tcurrent parameters: offset256 = 0x%x, fpga_prev_cntr = 0x%x, jpeg_wp = 0x%x, xferred = 0x%x\n", // stat.offset256, jptr->fpga_cntr_prev, jptr->jpeg_wp, xferred); return 1; } Loading Loading @@ -289,7 +316,8 @@ inline static void set_default_interframe(struct interframe_params_t *params) params->width = 2592; params->byrshift = 3; params->color = 0; params->quality2 = 100; params->quality2 = circbuf_quality; //params->quality2 = 100; } /** Loading @@ -313,6 +341,8 @@ inline struct interframe_params_t* updateIRQ_interframe(struct jpeg_ptr_t *jptr) // set_globalParam (0x306,get_globalParam (0x306)+1); //#endif dma_addr_t phys_addr; void *virt_addr; struct interframe_params_t *interframe; int len_offset = X393_BUFFSUB(jptr->jpeg_wp, INTERFRAME_PARAMS_SZ + 1); int jpeg_len = circbuf_priv_ptr[jptr->chn_num].buf_ptr[len_offset] & FRAME_LENGTH_MASK; Loading @@ -328,6 +358,19 @@ inline struct interframe_params_t* updateIRQ_interframe(struct jpeg_ptr_t *jptr) set_globalParam(G_FRAME_SIZE, jpeg_len); // invalidate CPU L1 and L2 caches phys_addr = circbuf_priv_ptr[jptr->chn_num].phys_addr + DW2BYTE(frame_params_offset); //virt_addr = circbuf_priv_ptr[jptr->chn_num].buf_ptr + frame_params_offset; virt_addr = interframe; __cpuc_flush_dcache_area(virt_addr, CHUNK_SIZE); outer_inv_range(phys_addr, phys_addr + (CHUNK_SIZE - 1)); if (jptr->chn_num == 0) { printk(KERN_DEBUG "this channel start address: phys_addr = 0x%x; buf_ptr = 0x%x", circbuf_priv_ptr[jptr->chn_num].phys_addr, circbuf_priv_ptr[jptr->chn_num].buf_ptr); printk(KERN_DEBUG "invalidate cache for channel %d: phys_addr = 0x%x; virt_addr = 0x%x\n", jptr->chn_num, phys_addr, virt_addr); } return interframe; } Loading Loading @@ -644,6 +687,9 @@ void reset_compressor(unsigned int chn) image_acq_priv.jpeg_ptr[chn].jpeg_rp = 0; image_acq_priv.jpeg_ptr[chn].fpga_cntr_prev = 0; image_acq_priv.jpeg_ptr[chn].flags = 0; /* debug code follows */ jpeg_hw_wp[chn] = 0; /* debug code end */ //update_irq_circbuf(jptr); local_irq_restore(flags); } Loading
src/include/elphel/c313a.h +1 −0 Original line number Diff line number Diff line Loading @@ -1361,6 +1361,7 @@ struct p_names_t { #define LSEEK_CIRC_WAIT 11 #define LSEEK_CIRC_FREE 12 #define LSEEK_CIRC_USED 13 #define LSEEK_CIRC_STOP_COMPRESSOR 14 #define LSEEK_HUFFMAN_DC0 1 #define LSEEK_HUFFMAN_AC0 2 Loading