os/linux-2.6-tag--devboard-R2_10-4/arch/cris/arch-v32/drivers/elphel/quantization_tables.c

Go to the documentation of this file.
00001 /*!********************************************************************************
00002  *! FILE NAME  : quantization_tables.c
00003  *! DESCRIPTION: Generation and handling quantization tables:
00004  *! - direct - to be included in the JPEG headers and
00005  *! - reverse - to go to the FPGA. Reverse are calculated as 0x10000/direct
00006  *! Based on standard JPEG quality quantization tables, with the following differences
00007  *! - FPGA uses multiplication by 65536/x instead of division by x
00008  *! - (to better handle JP4 flavors) it is possible to use Y tables for other components
00009  *!    possibly with different quality.
00010  *!
00011  *! Quality is represented by 2-byte value. Each byte uses Y table if the value is Q<128,
00012  *! and C table with (Q-128) if it is Q>=128.
00013  *! If the High byte is zero, it is treated as Q^0x80  (Q|=(Q^0x80)<<8) for compatibility
00014  *!  with a standard single-byte Q value
00015  *! FPGA table accomodates 8 pairs of quantization coefficients, so software tries
00016  *! to reuse loaded tables when possible
00017  *!
00018  *! Copyright (C) 2008 Elphel, Inc.
00019  *! -----------------------------------------------------------------------------**
00020  *!
00021  *!  This program is free software: you can redistribute it and/or modify
00022  *!  it under the terms of the GNU General Public License as published by
00023  *!  the Free Software Foundation, either version 3 of the License, or
00024  *!  (at your option) any later version.
00025  *!
00026  *!  This program is distributed in the hope that it will be useful,
00027  *!  but WITHOUT ANY WARRANTY; without even the implied warranty of
00028  *!  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00029  *!  GNU General Public License for more details.
00030  *!  You should have received a copy of the GNU General Public License
00031  *!  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00032  *! -----------------------------------------------------------------------------**
00033  *!  $Log: quantization_tables.c,v $
00034  *!  Revision 1.1.1.1  2008/11/27 20:04:01  elphel
00035  *!
00036  *!
00037  *!  Revision 1.8  2008/10/29 04:18:28  elphel
00038  *!  v.8.0.alpha10 made a separate structure for global parameters (not related to particular frames in a frame queue)
00039  *!
00040  *!  Revision 1.7  2008/10/23 08:08:41  elphel
00041  *!  reenabled irq in debug mode
00042  *!
00043  *!  Revision 1.6  2008/10/05 05:13:33  elphel
00044  *!  snapshot003
00045  *!
00046  *!  Revision 1.5  2008/09/12 00:24:00  elphel
00047  *!  removed cc353.c, cc353.h
00048  *!
00049  *!  Revision 1.4  2008/09/11 01:05:32  elphel
00050  *!  snapshot
00051  *!
00052  *!  Revision 1.3  2008/09/05 23:20:26  elphel
00053  *!  just a snapshot
00054  *!
00055  *!  Revision 1.2  2008/07/27 23:25:07  elphel
00056  *!  next snapshot
00057  *!
00058  *!  Revision 1.1  2008/06/08 23:46:45  elphel
00059  *!  added drivers files for handling quantization tables, gamma tables and the histograms
00060  *!
00061  *!
00062  */
00063 
00064 //copied from cxi2c.c - TODO:remove unneeded 
00065 
00066 #include <linux/module.h>
00067 #include <linux/mm.h>
00068 #include <linux/sched.h>
00069 #include <linux/slab.h>
00070 #include <linux/errno.h>
00071 #include <linux/kernel.h>
00072 #include <linux/fs.h>
00073 #include <linux/string.h>
00074 #include <linux/init.h>
00075 #include <linux/autoconf.h>
00076 #include <linux/vmalloc.h>
00077 
00078 #include <asm/system.h>
00079 #include <asm/byteorder.h> // endians
00080 #include <asm/io.h>
00081 
00082 #include <asm/irq.h>
00083 
00084 #include <asm/delay.h>
00085 #include <asm/uaccess.h>
00086 #include <asm/elphel/c313a.h>
00087 #include <asm/elphel/exifa.h>
00088 #include "fpgactrl.h"  // defines port_csp0_addr, port_csp4_addr 
00089 //#include "cc3x3.h"
00090 #include "fpga_io.h"
00091 
00092 #include "x3x3.h" // just for FPGA_NQTAB
00093 
00094 #include "framepars.h"
00095 //#include "fpga_io.h"//fpga_table_write_nice
00096 
00097 #include "quantization_tables.h"
00098 
00103 #if ELPHEL_DEBUG
00104   #define D15(x) { if (GLOBALPARS(G_DEBUG) & (1 <<15)) { x ;} }
00105   #define MDF15(x) { if (GLOBALPARS(G_DEBUG) & (1 <<15)) {printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);x ;} }
00106   #define D14(x) { if (GLOBALPARS(G_DEBUG) & (1 <<14)) { x ;} }
00107   #define MDF14(x) { if (GLOBALPARS(G_DEBUG) & (1 <<14)) {printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);x ;} }
00108   #define MDF(x) {printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);x ;}
00109 //  #define D1I(x)
00110   #define D1I(x) x
00111 #else
00112   #define D1I(x) x
00113   #define D15(x)
00114   #define MDF15(x)
00115   #define D14(x)
00116   #define MDF14(x)
00117   #define MDF(x)
00118 #endif
00119 
00120 
00121 #define QTABLE_SIZE 64 
00122 #define QTABLE_HEAD_CACHE 8 
00123    static unsigned int std_quant_tbls[2 * QTABLE_SIZE] = { 
00124 
00125     16,  11,  10,  16,  24,  40,  51,  61,
00126     12,  12,  14,  19,  26,  58,  60,  55,
00127     14,  13,  16,  24,  40,  57,  69,  56,
00128     14,  17,  22,  29,  51,  87,  80,  62,
00129     18,  22,  37,  56,  68, 109, 103,  77,
00130     24,  35,  55,  64,  81, 104, 113,  92,
00131     49,  64,  78,  87, 103, 121, 120, 101,
00132     72,  92,  95,  98, 112, 100, 103,  99,
00133 
00134     17,  18,  24,  47,  99,  99,  99,  99,
00135     18,  21,  26,  66,  99,  99,  99,  99,
00136     24,  26,  56,  99,  99,  99,  99,  99,
00137     47,  66,  99,  99,  99,  99,  99,  99,
00138     99,  99,  99,  99,  99,  99,  99,  99,
00139     99,  99,  99,  99,  99,  99,  99,  99,
00140     99,  99,  99,  99,  99,  99,  99,  99,
00141     99,  99,  99,  99,  99,  99,  99,  99
00142   };
00143 
00146 static unsigned char  qtable_cache [QTABLE_SIZE * 2 * QTABLE_HEAD_CACHE]; 
00147 static int            qtable_cache_values [QTABLE_HEAD_CACHE]; 
00148 static int            qtable_cache_next[QTABLE_HEAD_CACHE] ; 
00149 static int            qtable_cache_mre; 
00150 
00151 static int            qtable_fpga_values [FPGA_NQTAB]; 
00152 static int            qtable_fpga_next[FPGA_NQTAB] ; 
00153 static int            qtable_fpga_mre; 
00154 
00155 static int            qtable_cache_initialized;
00156 static int            qtable_fpga_initialized;
00157 
00161 void reset_qtables(void) {
00162  qtable_cache_initialized=0;
00163  qtable_fpga_initialized=0;
00164 }
00165 
00166 
00171 void init_qtable_head_cache (void) {
00172   D1I(unsigned long flags);
00173   int i;
00174   MDF(printk("\n"));
00175   D1I(local_irq_save(flags));
00177   for (i=0; i < QTABLE_HEAD_CACHE; i++) {
00178     qtable_cache_values[i]=-1; 
00179     qtable_cache_next[i]=i+1; 
00180     qtable_cache_mre=0;
00181   }
00182   qtable_cache_initialized=1;
00183   D1I(local_irq_restore(flags));
00184 }
00185 
00193 int get_qtable (int quality2, unsigned char *y_tab, unsigned char *c_tab) {
00194   D1I(unsigned long flags);
00195   int i,cache_index,cache_index_prev,q_type,quality,temp,tstart;
00196   int rslt=0;
00197   unsigned char * tab;
00198   const unsigned int zig_zag[QTABLE_SIZE] = {
00199        0, 1, 5, 6,14,15,27,28,
00200        2, 4, 7,13,16,26,29,42,
00201        3, 8,12,17,25,30,41,43,
00202        9,11,18,24,31,40,44,53,
00203       10,19,23,32,39,45,52,54,
00204       20,22,33,38,46,51,55,60,
00205       21,34,37,47,50,56,59,61,
00206       35,36,48,49,57,58,62,63   
00207    };
00208   if (qtable_cache_initialized==0) init_qtable_head_cache();
00209 
00210 
00211   MDF14(printk("quality2=0x%x\n",quality2));
00212   if (quality2<0) return -1;
00213   if (quality2<256) quality2 |= (quality2^0x80)<<8;
00214   MDF14(printk("quality2=0x%x\n",quality2));
00215   D1I(local_irq_save(flags));
00217   cache_index=qtable_cache_mre;
00218   cache_index_prev=-1;
00219   for (i=0; (i<(QTABLE_HEAD_CACHE-1)) && (qtable_cache_values[cache_index] != quality2) && (qtable_cache_values[cache_index]>=0); i++) {
00220    cache_index_prev=cache_index;
00221    cache_index=qtable_cache_next[cache_index];
00222   D14(printk("    ---i=%d, cache_index_prev=%d, cache_index=%d\n",i, cache_index_prev, cache_index));
00223   }
00225   if (i==(QTABLE_HEAD_CACHE-1)) { 
00226     qtable_cache_next[cache_index_prev]=qtable_cache_mre;
00227     qtable_cache_mre=cache_index_prev;
00228   MDF14(printk("qtable_cache_mre=%d\n",qtable_cache_mre));
00229   } else if (cache_index_prev>=0){ 
00230     qtable_cache_next[cache_index_prev]=qtable_cache_next[cache_index]; 
00231     qtable_cache_next[cache_index]=qtable_cache_mre; 
00232     qtable_cache_mre=cache_index; 
00233   MDF14(printk("qtable_cache_mre=%d\n",qtable_cache_mre));
00234   }
00236   if (qtable_cache_values[qtable_cache_mre] != quality2) { 
00237     rslt=1;
00238     for (q_type=0;q_type<2;q_type++) { //Y/C
00239       quality=(quality2>>(q_type?8:0)) & 0xff;
00240       tstart=(quality & 0x80)?QTABLE_SIZE:0;
00241       tab = & qtable_cache [QTABLE_SIZE * (2 * qtable_cache_mre + q_type)];
00242       quality &= 0x7f;
00243   MDF14(printk("tstart=%d, quality=%d\n",tstart,quality));
00245       if(quality <= 0)
00246         quality = 1;
00247       if(quality > 100)
00248         quality = 100;
00255       if(quality < 50)
00256         quality = 5000 / quality;
00257       else
00258         quality = 200 - quality * 2;
00259   MDF14(printk("q_type=%d, quality=%d\n",q_type,quality));
00260       for(i = 0; i < QTABLE_SIZE; i++) {
00261         temp = (std_quant_tbls[i+tstart] * quality + 50) / 100;
00263         if(temp <= 0) temp = 1;
00264         if(temp > 255) temp = 255;
00265         tab[zig_zag[i]]=temp;
00266       }
00267     }
00268   } 
00269 
00270   if (y_tab) memcpy (y_tab, & qtable_cache [QTABLE_SIZE * (2 * qtable_cache_mre + 0)],QTABLE_SIZE) ;
00271   if (c_tab) memcpy (c_tab, & qtable_cache [QTABLE_SIZE * (2 * qtable_cache_mre + 1)],QTABLE_SIZE) ;
00272   D1I(local_irq_restore(flags));
00273   MDF14(printk("y_tab=0x%x, c_tab=0x%x, rslt=%d\n",(int) y_tab, (int) c_tab, rslt));
00274   MDF15(if (y_tab) {printk("y_tab\n"); for (i=0;i<64;i++){if ((i & 7)==0) printk("\n");printk(" %02x",(int) y_tab[i]);} printk("\n");});
00275   MDF15(if (c_tab) {printk("c_tab\n"); for (i=0;i<64;i++){if ((i & 7)==0) printk("\n");printk(" %02x",(int) c_tab[i]);} printk("\n");});
00276   return rslt;
00277 }
00278 #if 0
00279 //Initialize quantization tables cache/FPGA
00280    init_qtable_head_cache();
00281    init_qtable_fpga();
00282 #endif
00283 
00288 void init_qtable_fpga(void) {
00289   D1I(unsigned long flags);
00290   int i;
00291   MDF14(printk("\n"));
00292   D1I(local_irq_save(flags));  
00293   for (i=0; i < FPGA_NQTAB; i++) {
00294     qtable_fpga_values[i]=-1; // undefined
00295     qtable_fpga_next[i]=i+1; // last value is invalid, but that's OK - it should not be used
00296     qtable_fpga_mre=0;
00297   }
00298   qtable_fpga_initialized=1;
00299   D1I(local_irq_restore(flags));
00300 }
00301 
00307 int set_qtable_fpga(int quality2) {
00308   D1I(unsigned long flags);
00309   int i,fpga_index,fpga_index_prev,q_type,quality,temp,tstart;
00310   unsigned short qtable_fpga[QTABLE_SIZE *2];
00311   unsigned short * tab;
00312   if (qtable_fpga_initialized==0) init_qtable_fpga();
00313   if (quality2<0) return -1;
00314   if (quality2<256) quality2 |= (quality2 ^ 0x80)<<8;
00315   MDF14(printk("quality2=0x%x\n",quality2)); // d050
00316   D1I(local_irq_save(flags));
00318   fpga_index=qtable_fpga_mre;
00319   fpga_index_prev=-1;
00320   for (i=0; (i<(FPGA_NQTAB-1)) && (qtable_fpga_values[fpga_index] != quality2) && (qtable_fpga_values[fpga_index]>=0); i++) {
00321    fpga_index_prev=fpga_index;
00322    fpga_index=qtable_fpga_next[fpga_index];
00323   D14(printk("    ---i=%d, fpga_index_prev=%d, fpga_index=%d\n",i, fpga_index_prev, fpga_index)); 
00324 
00325   }
00327   if (i==(FPGA_NQTAB-1)) { 
00328     qtable_fpga_next[fpga_index_prev]=qtable_fpga_mre;
00329     qtable_fpga_mre=fpga_index_prev;
00330   MDF14(printk("qtable_fpga_mre=%d\n",qtable_fpga_mre));  
00331   } else if (fpga_index_prev>=0) { 
00332     qtable_fpga_next[fpga_index_prev]=qtable_fpga_next[fpga_index]; 
00333     qtable_fpga_next[fpga_index]=qtable_fpga_mre; 
00334     qtable_fpga_mre=fpga_index; 
00335   MDF14(printk("qtable_fpga_mre=%d\n",qtable_fpga_mre));  
00336   }
00338   if (qtable_fpga_values[qtable_fpga_mre] != quality2) { 
00339     for (q_type=0;q_type<2;q_type++) { //Y/C
00340       quality=(quality2>>(q_type?8:0)) & 0xff;
00341   MDF14(printk("q_type=%d, quality=%d quality2=0x%x\n",q_type,quality,quality2));
00342       tstart=(quality & 0x80)?QTABLE_SIZE:0;
00343       tab = &qtable_fpga [QTABLE_SIZE * q_type];
00344       quality &= 0x7f;
00345   MDF14(printk("tstart=%d, quality=%d\n",tstart,quality)); //0, 1 - both times
00347       if(quality <= 0)
00348         quality = 1;
00349       if(quality > 100)
00350         quality = 100;
00357       if(quality < 50)
00358         quality = 5000 / quality;
00359       else
00360         quality = 200 - quality * 2;
00361   MDF14(printk("q_type=%d, quality=%d\n",q_type,quality));
00362       for(i = 0; i < QTABLE_SIZE; i++) {
00363         temp = (std_quant_tbls[i+tstart] * quality + 50) / 100;
00364         D15(if ((i & 7)==0) printk("\n");if (i==0) printk("\n");printk(" %08x",(int) temp));
00366         if(temp <= 0) temp = 1;
00367         if(temp > 255) temp = 255;
00368         temp = ((0x20000/temp) + 1) >> 1;
00369         if(temp > 0xffff) temp = 0xffff;
00370         tab[i]=temp;
00371       }
00372     }
00373     D15(printk("\n"));
00374     fpga_table_write_nice (CX313_FPGA_TABLES_QUANT+qtable_fpga_mre*QTABLE_SIZE, QTABLE_SIZE, (unsigned long *) qtable_fpga);
00375     MDF15(for (i=0;i<128;i++){if ((i & 7)==0) printk("\n");if ((i & 63)==0) printk("\n");printk(" %04x",(int) qtable_fpga[i]);} printk("\n"));
00376     MDF15(for (i=0;i<128;i++){if ((i & 7)==0) printk("\n");if ((i & 63)==0) printk("\n");printk(" %04x",std_quant_tbls[i]);} printk("\n"));
00377   } 
00378 
00379   D1I(local_irq_restore(flags));
00380   MDF14(printk("qtable_fpga_mre=%d\n",qtable_fpga_mre));
00381   return qtable_fpga_mre;
00382 }
00383 
00384 
00385 
00386 
00387 
00388 
00389 
00390 
00391 
00392 
00393 
00394 
00395 
00396 
00397 
00398 
00399 
00400 
00401 
00402 
00403 
00404 
00405 
00406 
00407 

Generated on Fri Nov 28 00:06:23 2008 for elphel by  doxygen 1.5.1