Commit 3437e6f6 authored by Oleg Dzhimiev's avatar Oleg Dzhimiev
Browse files

mt9f002: vertical and horizontal flips (mirroring)

parent 73cd475f
Loading
Loading
Loading
Loading
+94 −89
Original line number Original line Diff line number Diff line
@@ -760,6 +760,26 @@ int mt9f002_calc_frame_length_lines(int y_addr_start,
	return v0;
	return v0;
}
}


// also defines vertical blanking
int mt9f002_calc_frame_length_lines_2(int height,
									  int min_frame_blanking_lines){

	int v0;

	int subsampling_factor = 1;

	v0 = height/subsampling_factor + min_frame_blanking_lines;

	/*
	if (coarse_exposure>(v0-1)){
		v0 = coarse_exposure + 1;
		pr_info("frame_length_lines will get extended\n");
	}
	*/

	return v0;
}

// also defines horizontal blanking
// also defines horizontal blanking
int mt9f002_calc_line_length_pck(int x_addr_start,
int mt9f002_calc_line_length_pck(int x_addr_start,
								   int x_addr_end,
								   int x_addr_end,
@@ -845,8 +865,13 @@ int mt9f002_pgm_window_common (int sensor_port, ///< sensor port
    //int min_line_length_pck = 0x04c8;
    //int min_line_length_pck = 0x04c8;


    int ww_odd_inc = 1;
    int ww_odd_inc = 1;
    // fll - frame length lines
    // llp - line length pck
    int fll, llp;
    int fll, llp;


    int whs_vact_delay = 0;
    int whe_vact_delay = 0;

    dev_dbg(g_dev_ptr,"{%d}  frame16=%d\n",sensor_port,frame16);
    dev_dbg(g_dev_ptr,"{%d}  frame16=%d\n",sensor_port,frame16);
    if (frame16 >= PARS_FRAMES) return -1; // wrong frame
    if (frame16 >= PARS_FRAMES) return -1; // wrong frame


@@ -867,10 +892,10 @@ int mt9f002_pgm_window_common (int sensor_port, ///< sensor port
    compressor_margin = (thispars->pars[P_SENSOR_PIXH] - thispars->pars[P_WOI_WIDTH]) >> 1;
    compressor_margin = (thispars->pars[P_SENSOR_PIXH] - thispars->pars[P_WOI_WIDTH]) >> 1;
    //pr_info("Compressor margin = %d\n",compressor_margin);
    //pr_info("Compressor margin = %d\n",compressor_margin);


    // 10338 is _not_ flipped (as the other boards, but for legacy compatibility....)
    flip=((thispars->pars[P_FLIPH] & 1) | ((thispars->pars[P_FLIPV] & 1) << 1 )) ^ sensor->init_flips;
    flip=((thispars->pars[P_FLIPH] & 1) | ((thispars->pars[P_FLIPV] & 1) << 1 )) ^ sensor->init_flips;
    flipX =  flip & 1;
    flipX =  flip & 1;
    flipY = (flip & 2)? 1:0;
    flipY = (flip & 2)? 1:0;

    d = 2 * bh * (ww / (2 * bh));
    d = 2 * bh * (ww / (2 * bh));


    // correct window width if needed
    // correct window width if needed
@@ -901,21 +926,24 @@ int mt9f002_pgm_window_common (int sensor_port, ///< sensor port
    // get back to this
    // get back to this
    if (!thispars->pars[P_OVERSIZE]) {
    if (!thispars->pars[P_OVERSIZE]) {


        if(flipX) {
        //if(flipX) {
        	//pr_info("{%d} flipX = %d\n",sensor_port, flipX);
            //wl = sensor->clearWidth - ww - wl - (2 * COLOR_MARGINS) * dh;
            wl = sensor->clearWidth - ww - wl - (2 * COLOR_MARGINS) * dh;
            //if (wl < 0) wl = 0;
            if(wl < 0) wl = 0;
        //}
        }
        //if(flipY) {
        if(flipY) {
        //    wt = sensor->clearHeight - wh - wt - (2 * COLOR_MARGINS) * dv;
        	//pr_info("{%d} flipY = %d\n",sensor_port, flipY);
        //    if (wt < 0) wt = 0;
            wt = sensor->clearHeight - wh - wt - (2 * COLOR_MARGINS) * dv;
        //}
            if(wt < 0) wt = 0;

        }
        // apply clearTop/clearLeft
        // apply clearTop/clearLeft
        wt = (wt + sensor->clearTop) & 0xfffe;
        wt = (wt + sensor->clearTop) & 0xfffe;
        wl = (wl + sensor->clearLeft) & 0xfffe;
        wl = (wl + sensor->clearLeft) & 0xfffe;

        dev_dbg(g_dev_ptr,"{%d} wl =0x%x, wt=0x%x\n",sensor_port, wl, wt);
        dev_dbg(g_dev_ptr,"{%d} wl =0x%x, wt=0x%x\n",sensor_port, wl, wt);
        //pr_info("{%d} wl =0x%x, wt=0x%x\n",sensor_port, wl, wt);

        // apply VACT_DELAY
        whs_vact_delay = MT9F002_VACT_DELAY*(flipX?0:1);
        whe_vact_delay = MT9F002_VACT_DELAY*(dv+(flipX?1:0));


        /*
        /*
        // apply binning restrictions
        // apply binning restrictions
@@ -928,15 +956,18 @@ int mt9f002_pgm_window_common (int sensor_port, ///< sensor port
			i += d;
			i += d;
		wl = i;
		wl = i;
		*/
		*/
    // if P_OVERSIZE
    }else{
    	whe_vact_delay = MT9F002_VACT_DELAY*(dv+1);
    }
    }


    wws = wl;
    wws = wl;
    wwe = wws + ww - 1;
    wwe = wws + ww - 1;


    // need sensor->clearTop-MT9F002_VACT_DELAY - beacause the 1st 2 rows are ignored
    // need sensor->clearTop-MT9F002_VACT_DELAY - beacause the 1st 2 rows are ignored
    whs = wt - MT9F002_VACT_DELAY;
    whs = wt - whs_vact_delay;
    //whe = whs + wh + MT9F002_VACT_DELAY*(dv+1) - 1; // ?!
    //whe = whs + wh + MT9F002_VACT_DELAY*(dv+1) - 1; // ?!
    whe = whs + wh + MT9F002_VACT_DELAY*(dv) - 1;
    whe = whs + wh + whe_vact_delay - 1;
    // will be different if binning/skipping
    // will be different if binning/skipping
    wh = whe - whs + 1;
    wh = whe - whs + 1;


@@ -974,7 +1005,8 @@ int mt9f002_pgm_window_common (int sensor_port, ///< sensor port
        		sensor_port, sensor_port, frame16, (int) P_MT9F002_Y_OUTPUT_SIZE, (int) wh);
        		sensor_port, sensor_port, frame16, (int) P_MT9F002_Y_OUTPUT_SIZE, (int) wh);
    }
    }


    // recalc something after this one?
    /*
    // this is NOT needed when woi sizes change
    //fll = mt9f002_calc_frame_length_lines(thispars);
    //fll = mt9f002_calc_frame_length_lines(thispars);
    fll = mt9f002_calc_frame_length_lines(whs,whe,min_frame_blanking_lines);
    fll = mt9f002_calc_frame_length_lines(whs,whe,min_frame_blanking_lines);
    // this sets the vertical blanking
    // this sets the vertical blanking
@@ -983,6 +1015,7 @@ int mt9f002_pgm_window_common (int sensor_port, ///< sensor port
    			(int) thispars->pars[P_SENSOR_REGS+P_MT9F002_FRAME_LENGTH_LINES], fll);
    			(int) thispars->pars[P_SENSOR_REGS+P_MT9F002_FRAME_LENGTH_LINES], fll);
        SET_SENSOR_MBPAR_LUT(sensor_port, frame16, P_MT9F002_FRAME_LENGTH_LINES, fll);
        SET_SENSOR_MBPAR_LUT(sensor_port, frame16, P_MT9F002_FRAME_LENGTH_LINES, fll);
    }
    }
    */


    // need this fix for max possible fps
    // need this fix for max possible fps
    if (ww >= X_OUTPUT_BORDER_SIZE){
    if (ww >= X_OUTPUT_BORDER_SIZE){
@@ -1001,6 +1034,13 @@ int mt9f002_pgm_window_common (int sensor_port, ///< sensor port


    // write flips and skips
    // write flips and skips
    // reg 0x3040 = P_REG_MT9F002_READ_MODE
    // reg 0x3040 = P_REG_MT9F002_READ_MODE
    v = (thispars->pars[P_SENSOR_REGS+P_MT9F002_READ_MODE] & 0x3fff) | // preserve other bits from shadows
        (flipX ? (1 << 14) : 0) | // FLIPH - will control just alternative rows
        (flipY ? (1 << 15) : 0) ; // FLIPV

    if (v != thispars->pars[P_SENSOR_REGS+P_MT9F002_READ_MODE]) {
    	SET_SENSOR_MBPAR_LUT(sensor_port, frame16, P_MT9F002_READ_MODE, v);
    }


    //P_MT9F002_READ_MODE
    //P_MT9F002_READ_MODE
    // bits
    // bits
@@ -1100,12 +1140,12 @@ int compare_to_trig_period_mt9f002(int sensor_port, ///< sensor po
}
}


/** Check if compressor can keep up, limit sensor FPS if needed
/** Check if compressor can keep up, limit sensor FPS if needed
 * FPS is limited by increasing verical blanking, it can not be be made too big, so this method does not work to make time lapse rate. horisontal blanking
 * FPS is limited by increasing vertical blanking, it can not be be made too big, so this method does not work to make time lapse rate.
 * is kept at minimum (to reduce ERS effect) if not specified. If it is specified (>minimal) - it will be used instead.
 * Horizontal blanking is kept at minimum (to reduce ERS effect) if not specified. If it is specified (>minimal) - it will be used instead.
 * calculate line period.
 * Calculate line period.
 *
 *
 * FIXME - uses P_VIRTUAL_WIDTH w/o decreasing it when changing image size? Replace VIRT_WIDTH with HOR_BANK?
 * FIXME - uses P_VIRTUAL_WIDTH w/o decreasing it when changing image size? Replace VIRT_WIDTH with HOR_BANK?
 * Or require always set them to zero when chnaging WOI?
 * Or require always set them to zero when changing WOI?
 * FIXME for multisensor - needs per-sensor individual parameters. This uses sensor registers, not the general parameters (i.e. height) */
 * FIXME for multisensor - needs per-sensor individual parameters. This uses sensor registers, not the general parameters (i.e. height) */
int mt9f002_pgm_limitfps   (int sensor_port,               ///< sensor port number (0..3)
int mt9f002_pgm_limitfps   (int sensor_port,               ///< sensor port number (0..3)
                            struct sensor_t * sensor,      ///< sensor static parameters (capabilities)
                            struct sensor_t * sensor,      ///< sensor static parameters (capabilities)
@@ -1121,8 +1161,10 @@ int mt9f002_pgm_limitfps (int sensor_port, ///< sensor port numb


    // decimation horizontal
    // decimation horizontal
    int dh = thispars->pars[P_DCM_HOR]?thispars->pars[P_DCM_HOR]:1;
    int dh = thispars->pars[P_DCM_HOR]?thispars->pars[P_DCM_HOR]:1;
    int dv = thispars->pars[P_DCM_VERT]?thispars->pars[P_DCM_VERT]:1;
    // width = PIXELS HORIZONTAL
    // width = PIXELS HORIZONTAL
    int ww = thispars->pars[P_SENSOR_PIXH] * dh;
    int ww = thispars->pars[P_SENSOR_PIXH] * dh;
    int wh = thispars->pars[P_SENSOR_PIXV] * dv;


    int binning_cost = 0;
    int binning_cost = 0;
    int width,i;
    int width,i;
@@ -1134,8 +1176,10 @@ int mt9f002_pgm_limitfps (int sensor_port, ///< sensor port numb
    int height;
    int height;
    // virtual height read from sensor register
    // virtual height read from sensor register
    int virt_height;
    int virt_height;
    // minimum allowed by sensor for given wxh
    int virt_height_min;
    // virtual height calculated from trig_period
    // virtual height calculated from trig_period
    int virt_height_trig;
    int virt_height_trig = 0;
    int vert_blank;
    int vert_blank;


    uint64_t ull_fp1000s;
    uint64_t ull_fp1000s;
@@ -1236,14 +1280,16 @@ int mt9f002_pgm_limitfps (int sensor_port, ///< sensor port numb
  	  if((height * dv) < wh) height++;
  	  if((height * dv) < wh) height++;
    */
    */


    height = thispars->pars[P_SENSOR_PIXV];
    // this should be based on exposure
    // this should be based on exposure
    //virt_height = height + sensor->minVertBlank;
    //virt_height = height + sensor->minVertBlank;
    //virt_height = mt9f002_calc_frame_length_lines(thispars);
    //virt_height = mt9f002_calc_frame_length_lines(thispars);


    // this is allowed minimum
    // this is allowed minimum
    virt_height_min = mt9f002_calc_frame_length_lines_2(wh,thispars->pars[P_SENSOR_REGS+P_MT9F002_MIN_FRAME_BLANKING_LINES]);
    // this is current setting
    virt_height = thispars->pars[P_SENSOR_REGS+P_MT9F002_FRAME_LENGTH_LINES];
    virt_height = thispars->pars[P_SENSOR_REGS+P_MT9F002_FRAME_LENGTH_LINES];


    // override if really needed
    if (thispars->pars[P_VIRT_KEEP]) {
    if (thispars->pars[P_VIRT_KEEP]) {
        if (virt_height < thispars->pars[P_VIRT_HEIGHT]) {
        if (virt_height < thispars->pars[P_VIRT_HEIGHT]) {
            virt_height = thispars->pars[P_VIRT_HEIGHT];
            virt_height = thispars->pars[P_VIRT_HEIGHT];
@@ -1252,6 +1298,8 @@ int mt9f002_pgm_limitfps (int sensor_port, ///< sensor port numb


    dev_dbg(g_dev_ptr,"{%d} height =%d(0x%x), virt_height=%d(0x%x)\n",sensor_port,height,height,virt_height,virt_height);
    dev_dbg(g_dev_ptr,"{%d} height =%d(0x%x), virt_height=%d(0x%x)\n",sensor_port,height,height,virt_height,virt_height);


    // this is related to the case when TRIG_PERIOD is 'jumping' back and forth initialization bug
    if (thispars->pars[P_TRIG_PERIOD]>=256){
        // trig_period can be long, but it is already compared to P_PERIOD_MIN (compressor capability)
        // trig_period can be long, but it is already compared to P_PERIOD_MIN (compressor capability)
        trig_period = camsync_to_sensor(thispars->pars[P_TRIG_PERIOD], thispars->pars[P_CLK_SENSOR]);
        trig_period = camsync_to_sensor(thispars->pars[P_TRIG_PERIOD], thispars->pars[P_CLK_SENSOR]);


@@ -1266,6 +1314,10 @@ int mt9f002_pgm_limitfps (int sensor_port, ///< sensor port numb
    		virt_height_trig = 0xffff;
    		virt_height_trig = 0xffff;
    	}
    	}


        // compare against minimum
        if (virt_height_trig < virt_height_min) virt_height_trig = virt_height_min;
    }

	// round up? no
	// round up? no
	//if ((row_time_in_pixels * virt_height_min) < trig_period) virt_height_min++;
	//if ((row_time_in_pixels * virt_height_min) < trig_period) virt_height_min++;


@@ -1273,7 +1325,10 @@ int mt9f002_pgm_limitfps (int sensor_port, ///< sensor port numb
	//if (virt_height < virt_height_min) virt_height = virt_height_min;
	//if (virt_height < virt_height_min) virt_height = virt_height_min;


	// update except if zero
	// update except if zero
	if (virt_height_trig) virt_height = virt_height_trig;

	if (virt_height_trig) {
		virt_height = virt_height_trig;
	}


	dev_dbg(g_dev_ptr,"{%d} height =%d(0x%x), modified virt_height=%d(0x%x)\n",sensor_port,height,height,virt_height,virt_height);
	dev_dbg(g_dev_ptr,"{%d} height =%d(0x%x), modified virt_height=%d(0x%x)\n",sensor_port,height,height,virt_height,virt_height);


@@ -1500,58 +1555,6 @@ int mt9f002_pgm_exposure (int sensor_port, ///< sensor port number
	}
	}


    /*
    /*
    dev_dbg(g_dev_ptr,"{%d} sensor_port=%d,  frame16=%d, frame=0x%lx (%s)exposure=0x%lx, (%s)video_exposure=0x%lx\n",sensor_port, sensor_port, frame16, thispars->pars[P_FRAME], FRAMEPAR_MODIFIED(P_EXPOS)?"*":" ",thispars->pars[P_EXPOS],FRAMEPAR_MODIFIED(P_VEXPOS)?"*":" ",thispars->pars[P_VEXPOS] );
    dev_dbg(g_dev_ptr,"{%d}  row_time_in_pixels=0x%x\n",sensor_port, row_time_in_pixels); // 0
    //vert_blank=        thispars->pars[P_SENSOR_REGS+P_MT9X001_VERTBLANK ];
    vert_blank=0;

    dev_dbg(g_dev_ptr,"{%d}  vert_blank=0x%x\n",sensor_port,vert_blank); // 0
    // if video exposure is non-zero, P_VEXPOS is marked as modified or P_EXPOS is not modified - use video exposure (lines), else - absolute exposure (usec)
    if ((FRAMEPAR_MODIFIED(P_VEXPOS) || ! (FRAMEPAR_MODIFIED(P_EXPOS) || FRAMEPAR_MODIFIED(P_VIRT_WIDTH)) )) { // use number of lines

    	dev_dbg(g_dev_ptr,"{%d}  exposure=%d (0x%x), video_exposure=%d (0x%x)\n",sensor_port, (int) thispars->pars[P_VEXPOS], (int) thispars->pars[P_VEXPOS], (int) video_exposure, (int) video_exposure);
#if USELONGLONG
        ull_exposure= ((long long)(video_exposure * row_time_in_pixels)) * ((long long) 1000000);
#ifdef __div64_32
        __div64_32(&ull_exposure, sclk);
#else
        do_div(ull_exposure, sclk);
//        ull_exposure /= sclk;
#endif
        exposure= ull_exposure;
#else
        exposure = (100*video_exposure * row_time_in_pixels) / (sclk/10000); // in microseconds
#endif
        use_vexp=1;
    } else { // use time in microseconds
        exposure = thispars->pars[P_EXPOS];
#if USELONGLONG
        ull_video_exposure= (long long) exposure  * (long long) sclk;
#ifdef __div64_32
        __div64_32(&ull_video_exposure, row_time_in_pixels);
        __div64_32(&ull_video_exposure, 1000000);
#else
        do_div(ull_video_exposure, row_time_in_pixels);
        do_div(ull_video_exposure, 1000000);
//        ull_video_exposure /= row_time_in_pixels;
//        ull_video_exposure /= 1000000;
#endif
        video_exposure= ull_video_exposure;
#else
        ///TODO - use shifts, not division where possible?
        if (exposure<10000) { // <0.01 sec
            video_exposure = ( exposure        * (sclk/1000))/ (row_time_in_pixels*1000);
        } else if (exposure<100000) { // 0.1 sec
            video_exposure = ( (exposure/10)   * (sclk/1000))/ (row_time_in_pixels * 100);
        } else if (exposure<1000000) { // 1.0 sec
            video_exposure = ( (exposure/100)  * (sclk/1000))/ (row_time_in_pixels * 10);
        } else {
            video_exposure = ( (exposure/1000) * (sclk/1000))/ (row_time_in_pixels );
        }
#endif
    }
    if (exposure <1)       exposure=1;
    if (video_exposure <1) video_exposure=1;


    // is video exposure longer than maximal for the sensor?
    // is video exposure longer than maximal for the sensor?
    if (video_exposure  > sensor->maxShutter) {
    if (video_exposure  > sensor->maxShutter) {
@@ -1641,12 +1644,14 @@ int mt9f002_pgm_exposure (int sensor_port, ///< sensor port number
    }
    }
    */
    */


    /*
    // update
    // update
    if (virt_height != thispars->pars[P_SENSOR_REGS+P_MT9F002_FRAME_LENGTH_LINES]){
    if (virt_height != thispars->pars[P_SENSOR_REGS+P_MT9F002_FRAME_LENGTH_LINES]){
    	//pr_info("LIMIT_FPS, old frame_length_lines=0x%08x, new frame_length_lines=0x%08x\n",
    	//pr_info("LIMIT_FPS, old frame_length_lines=0x%08x, new frame_length_lines=0x%08x\n",
    	//		thispars->pars[P_SENSOR_REGS+P_MT9F002_FRAME_LENGTH_LINES],virt_height);
    	//		thispars->pars[P_SENSOR_REGS+P_MT9F002_FRAME_LENGTH_LINES],virt_height);
    	SET_SENSOR_MBPAR_LUT(sensor_port, frame16, P_MT9F002_FRAME_LENGTH_LINES, virt_height);
    	SET_SENSOR_MBPAR_LUT(sensor_port, frame16, P_MT9F002_FRAME_LENGTH_LINES, virt_height);
    }
    }
    */


    // coarse integration time
    // coarse integration time
    if (coarse_exposure != thispars->pars[P_SENSOR_REGS+P_MT9F002_COARSE_INTEGRATION_TIME]) {
    if (coarse_exposure != thispars->pars[P_SENSOR_REGS+P_MT9F002_COARSE_INTEGRATION_TIME]) {