diff options
author | mark gutman <r58412@freescale.com> | 2010-05-05 21:16:44 +0300 |
---|---|---|
committer | mark gutman <r58412@freescale.com> | 2010-05-16 14:58:45 +0300 |
commit | 1975b9985311cb32dfe9b5eb3dcc8fcda63a07d2 (patch) | |
tree | cfc570d0ea36402ff03fc18cdcdbca0f653dfc97 /drivers | |
parent | ce7002fc219286689d869a3350eab73f1e777584 (diff) |
ENGR00123294 MX53: 4 stripes algorithm for support resizing for big screen
The updated algorithm allows output frame size up to 2048x2048
Signed-off-by: Mark Gutman <Mark.Gutman@freescale.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/video/mxc/output/mxc_v4l2_output.c | 215 | ||||
-rw-r--r-- | drivers/media/video/mxc/output/mxc_v4l2_output.h | 6 | ||||
-rw-r--r-- | drivers/mxc/ipu3/ipu_calc_stripes_sizes.c | 2 | ||||
-rw-r--r-- | drivers/mxc/ipu3/ipu_ic.c | 22 | ||||
-rw-r--r-- | drivers/mxc/ipu3/ipu_param_mem.h | 6 |
5 files changed, 174 insertions, 77 deletions
diff --git a/drivers/media/video/mxc/output/mxc_v4l2_output.c b/drivers/media/video/mxc/output/mxc_v4l2_output.c index 6a91440f6fbe..b783baae8040 100644 --- a/drivers/media/video/mxc/output/mxc_v4l2_output.c +++ b/drivers/media/video/mxc/output/mxc_v4l2_output.c @@ -70,7 +70,7 @@ static spinlock_t g_lock = SPIN_LOCK_UNLOCKED; static int last_index_n; static int last_index_c; static unsigned int ipu_ic_out_max_width_size; - +static unsigned int ipu_ic_out_max_height_size; /* debug counters */ uint32_t g_irq_cnt; uint32_t g_buf_output_cnt; @@ -489,6 +489,7 @@ static void mxc_v4l2out_timer_handler(unsigned long arg) 0,/* vout->next_rdy_ipu_buf,*/ (vout->v4l2_bufs[index].m.offset) + vout->pp_left_stripe.input_column + + vout->pp_up_stripe.input_column * vout->bytesperline + current_field_offset); /* the U/V offset has to be updated inside of IDMAC */ @@ -501,9 +502,9 @@ static void mxc_v4l2out_timer_handler(unsigned long arg) vout->bytesperline, vout->offset.u_offset, vout->offset.v_offset, - 0, - vout->pp_left_stripe.input_column + current_field_offset); - + vout->pp_up_stripe.input_column, + vout->pp_left_stripe.input_column + + current_field_offset); } else ret = ipu_update_channel_buffer(vout->post_proc_ch, IPU_INPUT_BUFFER, @@ -541,12 +542,15 @@ static irqreturn_t mxc_v4l2out_work_irq_handler(int irq, void *dev_id) int index; unsigned long lock_flags = 0; vout_data *vout = dev_id; - int pp_out_buf_num = 0; + int pp_out_buf_left_right = 0; int disp_buf_num = 0; int disp_buf_num_next = 1; + int local_buffer = 0; int pp_out_buf_offset = 0; + int pp_out_buf_up_down = 0; int release_buffer = 0; - u32 eba_offset; + u32 eba_offset = 0; + u32 vertical_offset = 0; u16 x_pos; u16 y_pos; int ret = -1; @@ -564,17 +568,37 @@ static irqreturn_t mxc_v4l2out_work_irq_handler(int irq, void *dev_id) if (last_buf != -1) { /* If IC split mode on, update output buffer number */ if (vout->pp_split) { - pp_out_buf_num = vout->pp_split_buf_num & 1;/* left/right stripe */ - disp_buf_num = vout->pp_split_buf_num >> 1; - disp_buf_num_next = ((vout->pp_split_buf_num+2) & 3) >> 1; - if (!pp_out_buf_num) {/* next buffer is right stripe*/ - eba_offset = vout->pp_right_stripe.input_column;/*always right stripe*/ + pp_out_buf_up_down = vout->pp_split_buf_num & 1;/* left/right stripe */ + pp_out_buf_left_right = (vout->pp_split_buf_num >> 1) & 1; /* up/down */ + local_buffer = (vout->pp_split == 1) ? pp_out_buf_up_down : + pp_out_buf_left_right; + disp_buf_num = vout->pp_split_buf_num >> 2; + disp_buf_num_next = + ((vout->pp_split_buf_num + (vout->pp_split << 0x1)) & 7) >> 2; + if ((!pp_out_buf_left_right) || + ((!pp_out_buf_up_down) && (vout->pp_split == 1))) { + if (vout->pp_split == 1) { + eba_offset = ((pp_out_buf_left_right + pp_out_buf_up_down) & 1) ? + vout->pp_right_stripe.input_column : + vout->pp_left_stripe.input_column; + vertical_offset = pp_out_buf_up_down ? + vout->pp_up_stripe.input_column : + vout->pp_down_stripe.input_column; + + } else { + eba_offset = pp_out_buf_left_right ? + vout->pp_left_stripe.input_column : + vout->pp_right_stripe.input_column; + vertical_offset = pp_out_buf_left_right ? + vout->pp_up_stripe.input_column : + vout->pp_down_stripe.input_column; + } + ret = ipu_update_channel_buffer(vout->post_proc_ch, IPU_INPUT_BUFFER, - 1, /* right stripe */ + (1 - local_buffer), (vout->v4l2_bufs[vout->ipu_buf[disp_buf_num]].m.offset) - + eba_offset); - + + eba_offset + vertical_offset * vout->bytesperline); ret += ipu_update_channel_offset(vout->post_proc_ch, IPU_INPUT_BUFFER, vout->v2f.fmt.pix.pixelformat, @@ -583,46 +607,65 @@ static irqreturn_t mxc_v4l2out_work_irq_handler(int irq, void *dev_id) vout->bytesperline, vout->offset.u_offset, vout->offset.v_offset, - 0, - vout->pp_right_stripe.input_column); + vertical_offset, + eba_offset); /* select right stripe */ ret += ipu_select_buffer(vout->post_proc_ch, - IPU_INPUT_BUFFER, 1); + IPU_INPUT_BUFFER, (1 - local_buffer)); if (ret < 0) dev_err(&vout->video_dev->dev, "unable to set IPU buffer ready\n"); + vout->next_rdy_ipu_buf = !vout->next_rdy_ipu_buf; + } else {/* last stripe is done, run display refresh */ + select_display_buffer(vout, disp_buf_num); vout->ipu_buf[vout->next_done_ipu_buf] = -1; vout->next_done_ipu_buf = !vout->next_done_ipu_buf; - - } else /* right stripe is done, run display refresh */ - select_display_buffer(vout, disp_buf_num); - - vout->next_rdy_ipu_buf = !vout->next_rdy_ipu_buf; + vout->next_rdy_ipu_buf = !vout->next_rdy_ipu_buf; + } /* offset for next buffer's EBA */ - pp_out_buf_offset = pp_out_buf_num ? vout->pp_right_stripe.output_column : - vout->pp_left_stripe.output_column; eba_offset = 0; + if (vout->pp_split == 1) { + pp_out_buf_offset = ((vout->pp_split_buf_num >> 1) & 1) ? + vout->pp_left_stripe.output_column : + vout->pp_right_stripe.output_column; + + eba_offset = ((vout->pp_split_buf_num & 1) ? + vout->pp_down_stripe.output_column : + vout->pp_up_stripe.output_column); + + } else { + pp_out_buf_offset = ((vout->pp_split_buf_num >> 1) & 1) ? + vout->pp_right_stripe.output_column : + vout->pp_left_stripe.output_column; + eba_offset = ((vout->pp_split_buf_num >> 1) & 1) ? + vout->pp_down_stripe.output_column : + vout->pp_up_stripe.output_column; + } + if (vout->cur_disp_output == 5) { x_pos = (vout->crop_current.left / 8) * 8; y_pos = vout->crop_current.top; - eba_offset = (vout->xres * y_pos + x_pos) * vout->bpp / 8; + eba_offset += (vout->xres * y_pos + x_pos) * vout->bpp / 8; } + /* next buffer update */ eba_offset = vout->display_bufs[disp_buf_num_next] + pp_out_buf_offset + eba_offset; ipu_update_channel_buffer(vout->post_proc_ch, IPU_OUTPUT_BUFFER, - pp_out_buf_num, eba_offset); + local_buffer, eba_offset); /* next buffer ready */ - ret = ipu_select_buffer(vout->post_proc_ch, IPU_OUTPUT_BUFFER, pp_out_buf_num); + ret = ipu_select_buffer(vout->post_proc_ch, IPU_OUTPUT_BUFFER, local_buffer); + + /* next stripe_buffer index 0..7 */ + vout->pp_split_buf_num = (vout->pp_split_buf_num + vout->pp_split) & 0x7; + - /* next stripe_buffer index 0..3 */ - vout->pp_split_buf_num = (vout->pp_split_buf_num + 1) & 3; } else { /* show to display */ select_display_buffer(vout, vout->next_done_ipu_buf); @@ -631,7 +674,7 @@ static irqreturn_t mxc_v4l2out_work_irq_handler(int irq, void *dev_id) } /* release buffer. For split mode: if second stripe is done */ - release_buffer = vout->pp_split ? pp_out_buf_num : 1; + release_buffer = vout->pp_split ? (!(vout->pp_split_buf_num & 0x3)) : 1; if (release_buffer) { if ((!INTERLACED_CONTENT(vout)) || (vout->next_done_ipu_buf)) { g_buf_output_cnt++; @@ -908,37 +951,66 @@ static int init_PP(ipu_channel_params_t *params, vout_data *vout, params->mem_pp_mem.in_pixel_fmt = vout->v2f.fmt.pix.pixelformat; params->mem_pp_mem.out_width = out_width; params->mem_pp_mem.out_height = out_height; - params->mem_pp_mem.out_resize_ratio = 0; /* 0 means unused */ - + params->mem_pp_mem.outh_resize_ratio = 0; /* 0 means unused */ + params->mem_pp_mem.outv_resize_ratio = 0; /* 0 means unused */ /* split IC by two stripes, the by pass is impossible*/ if (vout->pp_split) { - ipu_calc_stripes_sizes( - params->mem_pp_mem.in_width, /* input frame width;>1 */ - params->mem_pp_mem.out_width, /* output frame width; >1 */ - ipu_ic_out_max_width_size, - (((unsigned long long)1) << 32), /* 32bit for fractional*/ - 1, /* equal stripes */ - params->mem_pp_mem.in_pixel_fmt, - params->mem_pp_mem.out_pixel_fmt, - &(vout->pp_left_stripe), - &(vout->pp_right_stripe)); - - vout->pp_left_stripe.input_column = vout->pp_left_stripe.input_column * + vout->pp_left_stripe.input_column = 0; + vout->pp_left_stripe.output_column = 0; + vout->pp_right_stripe.input_column = 0; + vout->pp_right_stripe.output_column = 0; + vout->pp_up_stripe.input_column = 0; + vout->pp_up_stripe.output_column = 0; + vout->pp_down_stripe.input_column = 0; + vout->pp_down_stripe.output_column = 0; + if (vout->pp_split != 3) { + ipu_calc_stripes_sizes( + params->mem_pp_mem.in_width, /* input frame width;>1 */ + params->mem_pp_mem.out_width, /* output frame width; >1 */ + ipu_ic_out_max_width_size, + (((unsigned long long)1) << 32), /* 32bit for fractional*/ + 1, /* equal stripes */ + params->mem_pp_mem.in_pixel_fmt, + params->mem_pp_mem.out_pixel_fmt, + &(vout->pp_left_stripe), + &(vout->pp_right_stripe)); + + vout->pp_left_stripe.input_column = vout->pp_left_stripe.input_column * fmt_to_bpp(vout->v2f.fmt.pix.pixelformat) / 8; - vout->pp_left_stripe.output_column = vout->pp_left_stripe.output_column * + vout->pp_left_stripe.output_column = vout->pp_left_stripe.output_column * fmt_to_bpp(params->mem_pp_mem.out_pixel_fmt) / 8; - vout->pp_right_stripe.input_column = vout->pp_right_stripe.input_column * + vout->pp_right_stripe.input_column = vout->pp_right_stripe.input_column * fmt_to_bpp(vout->v2f.fmt.pix.pixelformat) / 8; - vout->pp_right_stripe.output_column = vout->pp_right_stripe.output_column * + vout->pp_right_stripe.output_column = vout->pp_right_stripe.output_column * fmt_to_bpp(params->mem_pp_mem.out_pixel_fmt) / 8; + /* updare parameters */ params->mem_pp_mem.in_width = vout->pp_left_stripe.input_width; params->mem_pp_mem.out_width = vout->pp_left_stripe.output_width; out_width = vout->pp_left_stripe.output_width; /* for using in ic_init*/ - params->mem_pp_mem.out_resize_ratio = vout->pp_left_stripe.irr; - + params->mem_pp_mem.outh_resize_ratio = vout->pp_left_stripe.irr; + } + if (vout->pp_split != 2) { + ipu_calc_stripes_sizes( + params->mem_pp_mem.in_height, /* input frame width;>1 */ + params->mem_pp_mem.out_height, /* output frame width; >1 */ + ipu_ic_out_max_height_size, + (((unsigned long long)1) << 32),/* 32bit for fractional */ + 1, /* equal stripes */ + params->mem_pp_mem.in_pixel_fmt, + params->mem_pp_mem.out_pixel_fmt, + &(vout->pp_up_stripe), + &(vout->pp_down_stripe)); + vout->pp_down_stripe.output_column = vout->pp_down_stripe.output_column * out_stride; + vout->pp_up_stripe.output_column = vout->pp_up_stripe.output_column * out_stride; + params->mem_pp_mem.outv_resize_ratio = vout->pp_up_stripe.irr; + params->mem_pp_mem.in_height = vout->pp_up_stripe.input_width;/*height*/ + out_height = vout->pp_up_stripe.output_width;/*height*/ + if (vout->pp_split == 3) + vout->pp_split = 2;/*2 vertical stripe as two horizontal stripes */ + } vout->pp_split_buf_num = 0; } @@ -1049,20 +1121,27 @@ static int init_PP(ipu_channel_params_t *params, vout_data *vout, ipu_update_channel_buffer(vout->post_proc_ch, IPU_INPUT_BUFFER, 0, vout->v4l2_bufs[vout->ipu_buf[0]].m.offset + - vout->pp_left_stripe.input_column); + vout->pp_left_stripe.input_column + + vout->pp_up_stripe.input_column * vout->bytesperline); + + ipu_update_channel_buffer(vout->post_proc_ch, IPU_INPUT_BUFFER, 1, vout->v4l2_bufs[vout->ipu_buf[0]].m.offset + - vout->pp_right_stripe.input_column); + vout->pp_right_stripe.input_column + + vout->pp_up_stripe.input_column * vout->bytesperline); + ipu_update_channel_buffer(vout->post_proc_ch, IPU_OUTPUT_BUFFER, 0, vout->display_bufs[0] + eba_offset + - vout->pp_left_stripe.output_column); + vout->pp_left_stripe.output_column + + vout->pp_up_stripe.output_column); ipu_update_channel_buffer(vout->post_proc_ch, IPU_OUTPUT_BUFFER, 1, vout->display_bufs[0] + eba_offset + - vout->pp_right_stripe.output_column); + vout->pp_right_stripe.output_column + + vout->pp_up_stripe.output_column); } return 0; @@ -1114,22 +1193,31 @@ static int mxc_v4l2out_streamon(vout_data * vout) vout->next_done_ipu_buf = 0; vout->next_rdy_ipu_buf = 1; vout->pp_split = 0; + ipu_ic_out_max_height_size = 1024; +#ifdef CONFIG_MXC_IPU_V1 + ipu_ic_out_max_width_size = 800; +#else + ipu_ic_out_max_width_size = 1024; +#endif + if ((out_width > ipu_ic_out_max_width_size) || + (out_height > ipu_ic_out_max_height_size)) + vout->pp_split = 4; if (!INTERLACED_CONTENT(vout)) { vout->next_done_ipu_buf = vout->next_rdy_ipu_buf = 0; vout->ipu_buf[0] = dequeue_buf(&vout->ready_q); -#ifdef CONFIG_MXC_IPU_V1 - ipu_ic_out_max_width_size = 800; -#else - ipu_ic_out_max_width_size = 1024; -#endif /* split IC by two stripes, the by pass is impossible*/ if ((out_width != vout->v2f.fmt.pix.width || out_height != vout->v2f.fmt.pix.height) && - out_width > ipu_ic_out_max_width_size) { - vout->pp_split = 1; + vout->pp_split) { vout->ipu_buf[1] = vout->ipu_buf[0]; vout->frame_count = 1; + if ((out_width > ipu_ic_out_max_width_size) && (out_height > ipu_ic_out_max_height_size)) + vout->pp_split = 1; /*4 stripes*/ + else if (!(out_height > ipu_ic_out_max_height_size)) + vout->pp_split = 2; /*two horizontal stripes */ + else + vout->pp_split = 3; /*2 vertical stripes*/ } else { vout->ipu_buf[1] = dequeue_buf(&vout->ready_q); vout->frame_count = 2; @@ -1442,7 +1530,11 @@ static int mxc_v4l2out_streamon(vout_data * vout) vout->display_input_ch = vout->post_proc_ch; memset(¶ms, 0, sizeof(params)); if (INTERLACED_CONTENT(vout)) { - rc = init_VDI(params, vout, dev, fbi, out_width, out_height); + if (vout->pp_split) { + dev_err(&vout->video_dev->dev, "VDI split has not supported yet.\n"); + return -1; + } else + rc = init_VDI(params, vout, dev, fbi, out_width, out_height); } else { rc = init_PP(¶ms, vout, dev, fbi, out_width, out_height); } @@ -1752,7 +1844,6 @@ static int mxc_v4l2out_s_fmt(vout_data * vout, struct v4l2_format *f) dev_err(&vout->video_dev->dev, "De-interlacing not supported in this device!\n"); vout->field_fmt = V4L2_FIELD_NONE; - break; case V4L2_FIELD_INTERLACED_BT: dev_err(&vout->video_dev->dev, "V4L2_FIELD_INTERLACED_BT field format not supported yet!\n"); diff --git a/drivers/media/video/mxc/output/mxc_v4l2_output.h b/drivers/media/video/mxc/output/mxc_v4l2_output.h index 64076a001c60..7a868f377018 100644 --- a/drivers/media/video/mxc/output/mxc_v4l2_output.h +++ b/drivers/media/video/mxc/output/mxc_v4l2_output.h @@ -140,8 +140,10 @@ typedef struct _vout_data { int pp_split; /* 0,1 */ struct stripe_param pp_left_stripe; struct stripe_param pp_right_stripe; /* struct for split parameters */ - /* IC ouput buffer number. Counting from 0 to 3 */ - int pp_split_buf_num; /* 0..3 */ + struct stripe_param pp_up_stripe; + struct stripe_param pp_down_stripe; + /* IC ouput buffer number. Counting from 0 to 7 */ + int pp_split_buf_num; /* 0..7 */ u16 bpp ; /* bit per pixel */ u16 xres; /* width of physical frame (BGs) */ u16 yres; /* heigth of physical frame (BGs)*/ diff --git a/drivers/mxc/ipu3/ipu_calc_stripes_sizes.c b/drivers/mxc/ipu3/ipu_calc_stripes_sizes.c index 6a29c90fe095..5d5e0b9155a0 100644 --- a/drivers/mxc/ipu3/ipu_calc_stripes_sizes.c +++ b/drivers/mxc/ipu3/ipu_calc_stripes_sizes.c @@ -260,7 +260,7 @@ int ipu_calc_stripes_sizes(const unsigned int input_frame_width, input_frame_width >> 1; left->output_width = right->output_width = right->output_column = output_frame_width >> 1; - left->input_column = right->input_column = 0; + left->input_column = 0; div = _do_div(((((u64)irr_steps) << 32) * (right->input_width - 1)), (right->output_width - 1)); left->irr = right->irr = truncate(0, div, 1); diff --git a/drivers/mxc/ipu3/ipu_ic.c b/drivers/mxc/ipu3/ipu_ic.c index 564fab0b699a..4edf0a51d22f 100644 --- a/drivers/mxc/ipu3/ipu_ic.c +++ b/drivers/mxc/ipu3/ipu_ic.c @@ -1,5 +1,5 @@ /* - * Copyright 2005-2009 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2005-2010 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -227,13 +227,13 @@ void _ipu_ic_init_prpvf(ipu_channel_params_t *params, bool src_is_csi) /* Setup horizontal resizing */ /* Upadeted for IC split case */ - if (!(params->mem_prp_vf_mem.out_resize_ratio)) { + if (!(params->mem_prp_vf_mem.outh_resize_ratio)) { _calc_resize_coeffs(params->mem_prp_vf_mem.in_width, params->mem_prp_vf_mem.out_width, &resizeCoeff, &downsizeCoeff); reg |= (downsizeCoeff << 14) | resizeCoeff; } else - reg |= params->mem_prp_vf_mem.out_resize_ratio; + reg |= params->mem_prp_vf_mem.outh_resize_ratio; __raw_writel(reg, IC_PRP_VF_RSC); @@ -349,13 +349,13 @@ void _ipu_ic_init_prpenc(ipu_channel_params_t *params, bool src_is_csi) /* Setup horizontal resizing */ /* Upadeted for IC split case */ - if (!(params->mem_prp_enc_mem.out_resize_ratio)) { + if (!(params->mem_prp_enc_mem.outh_resize_ratio)) { _calc_resize_coeffs(params->mem_prp_enc_mem.in_width, params->mem_prp_enc_mem.out_width, &resizeCoeff, &downsizeCoeff); reg |= (downsizeCoeff << 14) | resizeCoeff; } else - reg |= params->mem_prp_enc_mem.out_resize_ratio; + reg |= params->mem_prp_enc_mem.outh_resize_ratio; __raw_writel(reg, IC_PRP_ENC_RSC); @@ -418,20 +418,24 @@ void _ipu_ic_init_pp(ipu_channel_params_t *params) ipu_color_space_t in_fmt, out_fmt; /* Setup vertical resizing */ - _calc_resize_coeffs(params->mem_pp_mem.in_height, + if (!(params->mem_pp_mem.outv_resize_ratio)) { + _calc_resize_coeffs(params->mem_pp_mem.in_height, params->mem_pp_mem.out_height, &resizeCoeff, &downsizeCoeff); - reg = (downsizeCoeff << 30) | (resizeCoeff << 16); + reg = (downsizeCoeff << 30) | (resizeCoeff << 16); + } else { + reg = (params->mem_pp_mem.outv_resize_ratio) << 16; + } /* Setup horizontal resizing */ /* Upadeted for IC split case */ - if (!(params->mem_pp_mem.out_resize_ratio)) { + if (!(params->mem_pp_mem.outh_resize_ratio)) { _calc_resize_coeffs(params->mem_pp_mem.in_width, params->mem_pp_mem.out_width, &resizeCoeff, &downsizeCoeff); reg |= (downsizeCoeff << 14) | resizeCoeff; } else { - reg |= params->mem_pp_mem.out_resize_ratio; + reg |= params->mem_pp_mem.outh_resize_ratio; } __raw_writel(reg, IC_PP_RSC); diff --git a/drivers/mxc/ipu3/ipu_param_mem.h b/drivers/mxc/ipu3/ipu_param_mem.h index 02daf55438f6..434f4a4bb62a 100644 --- a/drivers/mxc/ipu3/ipu_param_mem.h +++ b/drivers/mxc/ipu3/ipu_param_mem.h @@ -462,7 +462,7 @@ static inline void _ipu_ch_offset_update(int ch, (uv_stride * vertical_offset / 2) + horizontal_offset / 2; v_offset = u_offset + (uv_stride * height / 2); - u_fix = u ? (u + (uv_stride * vertical_offset) + + u_fix = u ? (u + (uv_stride * vertical_offset / 2) + (horizontal_offset / 2) - (stride * vertical_offset) - (horizontal_offset)) : u_offset; @@ -513,9 +513,9 @@ static inline void _ipu_ch_offset_update(int ch, uv_stride = stride; u_offset = stride * (height - vertical_offset - 1) + (stride - horizontal_offset) + - (uv_stride * vertical_offset) + + (uv_stride * vertical_offset / 2) + horizontal_offset; - u_fix = u ? (u + (uv_stride * vertical_offset) + + u_fix = u ? (u + (uv_stride * vertical_offset / 2) + horizontal_offset - (stride * vertical_offset) - (horizontal_offset)) : u_offset; |