📄 blizzard.c
字号:
int gx1_out, gy1_out, gx2_out, gy2_out; int color_mode; int flags; int zoom_off; /* Global coordinates, relative to pixel 0,0 of the LCD */ gx1 = x + blizzard.plane[plane].pos_x; gy1 = y + blizzard.plane[plane].pos_y; gx2 = gx1 + w; gy2 = gy1 + h; flags = req->par.update.flags; if (flags & OMAPFB_FORMAT_FLAG_DOUBLE) { gx1_out = gx1; gy1_out = gy1; gx2_out = gx1 + w * 2; gy2_out = gy1 + h * 2; } else { gx1_out = x_out + blizzard.plane[plane].pos_x; gy1_out = y_out + blizzard.plane[plane].pos_y; gx2_out = gx1_out + w_out; gy2_out = gy1_out + h_out; } zoom_off = blizzard.zoom_on && gx1 == 0 && gy1 == 0 && w == blizzard.screen_width && h == blizzard.screen_height; blizzard.zoom_on = (!zoom_off && blizzard.zoom_on) || (w < w_out || h < h_out); for (i = 0; i < OMAPFB_PLANE_NUM; i++) { struct plane_info *p = &blizzard.plane[i]; int px1, py1; int px2, py2; int pw, ph; int pposx, pposy; unsigned long offset; if (!(blizzard.enabled_planes & (1 << i)) || (wnd_color_mode && i != plane)) { blizzard.int_ctrl->enable_plane(i, 0); continue; } /* Plane coordinates */ if (i == plane) { /* Plane in which we are doing the update. * Local coordinates are the one in the update * request. */ px1 = x; py1 = y; px2 = x + w; py2 = y + h; pposx = 0; pposy = 0; } else { /* Check if this plane has an overlapping part */ px1 = gx1 - p->pos_x; py1 = gy1 - p->pos_y; px2 = gx2 - p->pos_x; py2 = gy2 - p->pos_y; if (px1 >= p->width || py1 >= p->height || px2 <= 0 || py2 <= 0) { blizzard.int_ctrl->enable_plane(i, 0); continue; } /* Calculate the coordinates for the overlapping * part in the plane's local coordinates. */ pposx = -px1; pposy = -py1; if (px1 < 0) px1 = 0; if (py1 < 0) py1 = 0; if (px2 > p->width) px2 = p->width; if (py2 > p->height) py2 = p->height; if (pposx < 0) pposx = 0; if (pposy < 0) pposy = 0; } pw = px2 - px1; ph = py2 - py1; offset = p->offset + (p->scr_width * py1 + px1) * p->bpp / 8; if (wnd_color_mode) /* Window embedded in the plane with a differing * color mode / bpp. Calculate the number of DMA * transfer elements in terms of the plane's bpp. */ pw = (pw + 1) * bpp / p->bpp;#ifdef VERBOSE dev_dbg(blizzard.fbdev->dev, "plane %d offset %#08lx pposx %d pposy %d " "px1 %d py1 %d pw %d ph %d\n", i, offset, pposx, pposy, px1, py1, pw, ph);#endif blizzard.int_ctrl->setup_plane(i, OMAPFB_CHANNEL_OUT_LCD, offset, p->scr_width, pposx, pposy, pw, ph, p->color_mode); blizzard.int_ctrl->enable_plane(i, 1); } switch (wnd_color_mode) { case OMAPFB_COLOR_YUV420: color_mode = BLIZZARD_COLOR_YUV420; /* Currently only the 16 bits/pixel cycle format is * supported on the external interface. Adjust the number * of transfer elements per line for 12bpp format. */ w = (w + 1) * 3 / 4; break; default: color_mode = BLIZZARD_COLOR_RGB565; break; } blizzard_wait_line_buffer(); if (blizzard.last_color_mode == BLIZZARD_COLOR_YUV420) blizzard_wait_yyc(); blizzard.last_color_mode = color_mode; if (flags & OMAPFB_FORMAT_FLAG_TEARSYNC) enable_tearsync(gy1, w, h, blizzard.screen_height, h_out, flags & OMAPFB_FORMAT_FLAG_FORCE_VSYNC); else disable_tearsync(); set_window_regs(gx1, gy1, gx2, gy2, gx1_out, gy1_out, gx2_out, gy2_out, color_mode, zoom_off, flags); blizzard.extif->set_bits_per_cycle(16); /* set_window_regs has left the register index at the right * place, so no need to set it here. */ blizzard.extif->transfer_area(w, h, request_complete, req); return REQ_PENDING;}static int send_frame_handler(struct blizzard_request *req){ struct update_param *par = &req->par.update; int plane = par->plane;#ifdef VERBOSE dev_dbg(blizzard.fbdev->dev, "send_frame: x %d y %d w %d h %d " "x_out %d y_out %d w_out %d h_out %d " "color_mode %04x flags %04x planes %01x\n", par->x, par->y, par->width, par->height, par->out_x, par->out_y, par->out_width, par->out_height, par->color_mode, par->flags, blizzard.enabled_planes);#endif if (par->flags & OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY) disable_overlay(); if ((blizzard.enabled_planes & blizzard.vid_nonstd_color) || (blizzard.enabled_planes & blizzard.vid_scaled)) return do_full_screen_update(req); return do_partial_update(req, plane, par->x, par->y, par->width, par->height, par->out_x, par->out_y, par->out_width, par->out_height, par->color_mode, par->bpp);}static void send_frame_complete(void *data){}#define ADD_PREQ(_x, _y, _w, _h, _x_out, _y_out, _w_out, _h_out) do { \ req = alloc_req(); \ req->handler = send_frame_handler; \ req->complete = send_frame_complete; \ req->par.update.plane = plane_idx; \ req->par.update.x = _x; \ req->par.update.y = _y; \ req->par.update.width = _w; \ req->par.update.height = _h; \ req->par.update.out_x = _x_out; \ req->par.update.out_y = _y_out; \ req->par.update.out_width = _w_out; \ req->par.update.out_height = _h_out; \ req->par.update.bpp = bpp; \ req->par.update.color_mode = color_mode;\ req->par.update.flags = flags; \ list_add_tail(&req->entry, req_head); \} while(0)static void create_req_list(int plane_idx, struct omapfb_update_window *win, struct list_head *req_head){ struct blizzard_request *req; int x = win->x; int y = win->y; int width = win->width; int height = win->height; int x_out = win->out_x; int y_out = win->out_y; int width_out = win->out_width; int height_out = win->out_height; int color_mode; int bpp; int flags; unsigned int ystart = y; unsigned int yspan = height; unsigned int ystart_out = y_out; unsigned int yspan_out = height_out; flags = win->format & ~OMAPFB_FORMAT_MASK; color_mode = win->format & OMAPFB_FORMAT_MASK; switch (color_mode) { case OMAPFB_COLOR_YUV420: /* Embedded window with different color mode */ bpp = 12; /* X, Y, height must be aligned at 2, width at 4 pixels */ x &= ~1; y &= ~1; height = yspan = height & ~1; width = width & ~3; break; default: /* Same as the plane color mode */ bpp = blizzard.plane[plane_idx].bpp; break; } if (width * height * bpp / 8 > blizzard.max_transmit_size) { yspan = blizzard.max_transmit_size / (width * bpp / 8); yspan_out = yspan * height_out / height; ADD_PREQ(x, ystart, width, yspan, x_out, ystart_out, width_out, yspan_out); ystart += yspan; ystart_out += yspan_out; yspan = height - yspan; yspan_out = height_out - yspan_out; flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC; } ADD_PREQ(x, ystart, width, yspan, x_out, ystart_out, width_out, yspan_out);}static void auto_update_complete(void *data){ if (!blizzard.stop_auto_update) mod_timer(&blizzard.auto_update_timer, jiffies + BLIZZARD_AUTO_UPDATE_TIME);}static void blizzard_update_window_auto(unsigned long arg){ LIST_HEAD(req_list); struct blizzard_request *last; struct omapfb_plane_struct *plane; plane = blizzard.fbdev->fb_info[0]->par; create_req_list(plane->idx, &blizzard.auto_update_window, &req_list); last = list_entry(req_list.prev, struct blizzard_request, entry); last->complete = auto_update_complete; last->complete_data = NULL; submit_req_list(&req_list);}int blizzard_update_window_async(struct fb_info *fbi, struct omapfb_update_window *win, void (*complete_callback)(void *arg), void *complete_callback_data){ LIST_HEAD(req_list); struct blizzard_request *last; struct omapfb_plane_struct *plane = fbi->par; if (unlikely(blizzard.update_mode != OMAPFB_MANUAL_UPDATE)) return -EINVAL; if (unlikely(!blizzard.te_connected && (win->format & OMAPFB_FORMAT_FLAG_TEARSYNC))) return -EINVAL; create_req_list(plane->idx, win, &req_list); last = list_entry(req_list.prev, struct blizzard_request, entry); last->complete = complete_callback; last->complete_data = (void *)complete_callback_data; submit_req_list(&req_list); return 0;}EXPORT_SYMBOL(blizzard_update_window_async);static int update_full_screen(void){ return blizzard_update_window_async(blizzard.fbdev->fb_info[0], &blizzard.auto_update_window, NULL, NULL);}static int blizzard_setup_plane(int plane, int channel_out, unsigned long offset, int screen_width, int pos_x, int pos_y, int width, int height, int color_mode){ struct plane_info *p;#ifdef VERBOSE dev_dbg(blizzard.fbdev->dev, "plane %d ch_out %d offset %#08lx scr_width %d " "pos_x %d pos_y %d width %d height %d color_mode %d\n", plane, channel_out, offset, screen_width, pos_x, pos_y, width, height, color_mode);#endif if ((unsigned)plane > OMAPFB_PLANE_NUM) return -EINVAL; p = &blizzard.plane[plane]; switch (color_mode) { case OMAPFB_COLOR_YUV422: case OMAPFB_COLOR_YUY422: p->bpp = 16; blizzard.vid_nonstd_color &= ~(1 << plane); break; case OMAPFB_COLOR_YUV420: p->bpp = 12; blizzard.vid_nonstd_color |= 1 << plane; break; case OMAPFB_COLOR_RGB565: p->bpp = 16; blizzard.vid_nonstd_color &= ~(1 << plane); break; default: return -EINVAL; } p->offset = offset; p->pos_x = pos_x; p->pos_y = pos_y; p->width = width; p->height = height; p->scr_width = screen_width; if (!p->out_width) p->out_width = width; if (!p->out_height) p->out_height = height; p->color_mode = color_mode; return 0;}static int blizzard_set_scale(int plane, int orig_w, int orig_h, int out_w, int out_h){ struct plane_info *p = &blizzard.plane[plane]; int r; dev_dbg(blizzard.fbdev->dev, "plane %d orig_w %d orig_h %d out_w %d out_h %d\n", plane, orig_w, orig_h, out_w, out_h); if ((unsigned)plane > OMAPFB_PLANE_NUM) return -ENODEV; r = blizzard.int_ctrl->set_scale(plane, orig_w, orig_h, out_w, out_h); if (r < 0) return r; p->width = orig_w; p->height = orig_h; p->out_width = out_w; p->out_height = out_h; if (orig_w == out_w && orig_h == out_h) blizzard.vid_scaled &= ~(1 << plane); else blizzard.vid_scaled |= 1 << plane; return 0;}static int blizzard_enable_plane(int plane, int enable){ if (enable) blizzard.enabled_planes |= 1 << plane; else blizzard.enabled_planes &= ~(1 << plane); return 0;}static int sync_handler(struct blizzard_request *req){ complete(req->par.sync); return REQ_COMPLETE;}static void blizzard_sync(void){ LIST_HEAD(req_list); struct blizzard_request *req; struct completion comp; req = alloc_req(); req->handler = sync_handler; req->complete = NULL; init_completion(&comp); req->par.sync = ∁ list_add(&req->entry, &req_list); submit_req_list(&req_list); wait_for_completion(&comp);}static void blizzard_bind_client(struct omapfb_notifier_block *nb){ if (blizzard.update_mode == OMAPFB_MANUAL_UPDATE) { omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_READY); }}static int blizzard_set_update_mode(enum omapfb_update_mode mode){ if (unlikely(mode != OMAPFB_MANUAL_UPDATE && mode != OMAPFB_AUTO_UPDATE && mode != OMAPFB_UPDATE_DISABLED)) return -EINVAL; if (mode == blizzard.update_mode) return 0; dev_info(blizzard.fbdev->dev, "s1d1374x: setting update mode to %s\n", mode == OMAPFB_UPDATE_DISABLED ? "disabled" : (mode == OMAPFB_AUTO_UPDATE ? "auto" : "manual")); switch (blizzard.update_mode) { case OMAPFB_MANUAL_UPDATE: omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_DISABLED); break; case OMAPFB_AUTO_UPDATE: blizzard.stop_auto_update = 1; del_timer_sync(&blizzard.auto_update_timer); break; case OMAPFB_UPDATE_DISABLED: break; } blizzard.update_mode = mode; blizzard_sync(); blizzard.stop_auto_update = 0; switch (mode) { case OMAPFB_MANUAL_UPDATE: omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_READY); break; case OMAPFB_AUTO_UPDATE: blizzard_update_window_auto(0); break; case OMAPFB_UPDATE_DISABLED: break; } return 0;}static enum omapfb_update_mode blizzard_get_update_mode(void){ return blizzard.update_mode;}static inline void set_extif_timings(const struct extif_timings *t){ blizzard.extif->set_timings(t);}static inline unsigned long round_to_extif_ticks(unsigned long ps, int div){ int bus_tick = blizzard.extif_clk_period * div; return (ps + bus_tick - 1) / bus_tick * bus_tick;}static int calc_reg_timing(unsigned long sysclk, int div){ struct extif_timings *t; unsigned long systim; /* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns, * AccessTime 2 ns + 12.2 ns (regs), * WEOffTime = WEOnTime + 1 ns, * REOffTime = REOnTime + 12 ns (regs), * CSOffTime = REOffTime + 1 ns * ReadCycle = 2ns + 2*SYSCLK (regs), * WriteCycle = 2*SYSCLK + 2 ns, * CSPulseWidth = 10 ns */ systim = 1000000000 / (sysclk / 1000); dev_dbg(blizzard.fbdev->dev, "Blizzard systim %lu ps extif_clk_period %u div %d\n", systim, blizzard.extif_clk_period, div); t = &blizzard.reg_timings; memset(t, 0, sizeof(*t)); t->clk_div = div; t->cs_on_time = 0; t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div); t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div); t->access_time = round_to_extif_ticks(t->re_on_time + 12200, div); t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div); t->re_off_time = round_to_extif_ticks(t->re_on_time + 13000, div); t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div); t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div); if (t->we_cycle_time < t->we_off_time)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -