Lines Matching +full:video +full:- +full:mem

2  * linux/drivers/video/metronomefb.c -- FB driver for Metronome controller
12 * This work was made possible by help and equipment support from E-Ink
34 #include <linux/dma-mapping.h>
38 #include <video/metronomefb.h>
48 /* frame differs from image. frame includes non-visible pixels */
148 static u8 calc_cksum(int start, int end, u8 *mem) in calc_cksum() argument
154 tmp += mem[i]; in calc_cksum()
163 while (length--) in calc_img_cksum()
170 static int load_waveform(u8 *mem, size_t size, int m, int t, in load_waveform() argument
183 u8 *metromem = par->metromem_wfm; in load_waveform()
184 struct device *dev = par->info->device; in load_waveform()
187 epd_frame_table[par->dt].wfm_size = user_wfm_size; in load_waveform()
189 if (size != epd_frame_table[par->dt].wfm_size) { in load_waveform()
191 epd_frame_table[par->dt].wfm_size); in load_waveform()
192 return -EINVAL; in load_waveform()
195 wfm_hdr = (struct waveform_hdr *) mem; in load_waveform()
197 if (wfm_hdr->fvsn != 1) { in load_waveform()
198 dev_err(dev, "Error: bad fvsn %x\n", wfm_hdr->fvsn); in load_waveform()
199 return -EINVAL; in load_waveform()
201 if (wfm_hdr->luts != 0) { in load_waveform()
202 dev_err(dev, "Error: bad luts %x\n", wfm_hdr->luts); in load_waveform()
203 return -EINVAL; in load_waveform()
205 cksum = calc_cksum(32, 47, mem); in load_waveform()
206 if (cksum != wfm_hdr->wfm_cs) { in load_waveform()
208 wfm_hdr->wfm_cs); in load_waveform()
209 return -EINVAL; in load_waveform()
211 wfm_hdr->mc += 1; in load_waveform()
212 wfm_hdr->trc += 1; in load_waveform()
214 if (*(wfm_hdr->stuff2a + i) != 0) { in load_waveform()
216 return -EINVAL; in load_waveform()
224 if ((sizeof(*wfm_hdr) + wfm_hdr->trc) > size) in load_waveform()
225 return -EINVAL; in load_waveform()
227 for (i = sizeof(*wfm_hdr); i <= sizeof(*wfm_hdr) + wfm_hdr->trc; i++) { in load_waveform()
228 if (mem[i] > t) { in load_waveform()
229 trn = i - sizeof(*wfm_hdr) - 1; in load_waveform()
235 cksum_idx = sizeof(*wfm_hdr) + wfm_hdr->trc + 1; in load_waveform()
237 return -EINVAL; in load_waveform()
238 cksum = calc_cksum(sizeof(*wfm_hdr), cksum_idx, mem); in load_waveform()
239 if (cksum != mem[cksum_idx]) { in load_waveform()
241 " %x != %x\n", cksum, mem[cksum_idx]); in load_waveform()
242 return -EINVAL; in load_waveform()
246 wmta = get_unaligned_le32(wfm_hdr->wmta) & 0x00FFFFFF; in load_waveform()
249 return -EINVAL; in load_waveform()
250 cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem); in load_waveform()
251 if (cksum != mem[cksum_idx]) { in load_waveform()
253 " %x != %x\n", cksum, mem[cksum_idx]); in load_waveform()
254 return -EINVAL; in load_waveform()
258 tta = get_unaligned_le32(mem + wmta + m * 4) & 0x00FFFFFF; in load_waveform()
261 return -EINVAL; in load_waveform()
262 cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem); in load_waveform()
263 if (cksum != mem[cksum_idx]) { in load_waveform()
265 " %x != %x\n", cksum, mem[cksum_idx]); in load_waveform()
266 return -EINVAL; in load_waveform()
271 wfm_idx = get_unaligned_le32(mem + tta + trn * 4) & 0x00FFFFFF; in load_waveform()
274 return -EINVAL; in load_waveform()
277 v = mem[wfm_idx++]; in load_waveform()
278 if (v == wfm_hdr->swtb) { in load_waveform()
279 while (((v = mem[wfm_idx++]) != wfm_hdr->swtb) && in load_waveform()
286 if (v == wfm_hdr->endb) in load_waveform()
289 rl = mem[wfm_idx++]; in load_waveform()
296 return -EINVAL; in load_waveform()
297 cksum = calc_cksum(owfm_idx, cksum_idx, mem); in load_waveform()
298 if (cksum != mem[cksum_idx]) { in load_waveform()
300 " %x != %x\n", cksum, mem[cksum_idx]); in load_waveform()
301 return -EINVAL; in load_waveform()
303 par->frame_count = (mem_idx/64); in load_waveform()
320 if (par->metromem_cmd->opcode == 0xCC40) in metronome_display_cmd()
327 par->metromem_cmd->args[i] = 1 << 3 /* border update */ in metronome_display_cmd()
329 | (par->frame_count - 1) << 8; in metronome_display_cmd()
330 cs += par->metromem_cmd->args[i++]; in metronome_display_cmd()
333 memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2); in metronome_display_cmd()
335 par->metromem_cmd->csum = cs; in metronome_display_cmd()
336 par->metromem_cmd->opcode = opcode; /* display cmd */ in metronome_display_cmd()
338 return par->board->met_wait_event_intr(par); in metronome_display_cmd()
347 par->metromem_cmd->opcode = 0x1234; /* pwr up pseudo cmd */ in metronome_powerup_cmd()
348 cs = par->metromem_cmd->opcode; in metronome_powerup_cmd()
352 par->metromem_cmd->args[i] = 1024; in metronome_powerup_cmd()
353 cs += par->metromem_cmd->args[i]; in metronome_powerup_cmd()
357 memset(&par->metromem_cmd->args[i], 0, in metronome_powerup_cmd()
358 (ARRAY_SIZE(par->metromem_cmd->args) - i) * 2); in metronome_powerup_cmd()
360 par->metromem_cmd->csum = cs; in metronome_powerup_cmd()
363 par->board->set_rst(par, 1); in metronome_powerup_cmd()
366 par->board->set_stdby(par, 1); in metronome_powerup_cmd()
368 return par->board->met_wait_event(par); in metronome_powerup_cmd()
377 memcpy(par->metromem_cmd->args, epd_frame_table[par->dt].config, in metronome_config_cmd()
378 sizeof(epd_frame_table[par->dt].config)); in metronome_config_cmd()
380 memset(&par->metromem_cmd->args[4], 0, in metronome_config_cmd()
381 (ARRAY_SIZE(par->metromem_cmd->args) - 4) * 2); in metronome_config_cmd()
383 par->metromem_cmd->csum = 0xCC10; in metronome_config_cmd()
384 par->metromem_cmd->csum += calc_img_cksum(par->metromem_cmd->args, 4); in metronome_config_cmd()
385 par->metromem_cmd->opcode = 0xCC10; /* config cmd */ in metronome_config_cmd()
387 return par->board->met_wait_event(par); in metronome_config_cmd()
404 par->metromem_cmd->args[i] = 0; in metronome_init_cmd()
405 cs += par->metromem_cmd->args[i++]; in metronome_init_cmd()
408 memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2); in metronome_init_cmd()
410 par->metromem_cmd->csum = cs; in metronome_init_cmd()
411 par->metromem_cmd->opcode = 0xCC20; /* init cmd */ in metronome_init_cmd()
413 return par->board->met_wait_event(par); in metronome_init_cmd()
420 res = par->board->setup_io(par); in metronome_init_regs()
441 unsigned char *buf = par->info->screen_buffer; in metronomefb_dpy_update()
443 fbsize = par->info->fix.smem_len; in metronomefb_dpy_update()
445 memcpy(par->metromem_img, buf, fbsize); in metronomefb_dpy_update()
447 cksum = calc_img_cksum((u16 *) par->metromem_img, fbsize/2); in metronomefb_dpy_update()
448 *((u16 *)(par->metromem_img) + fbsize/2) = cksum; in metronomefb_dpy_update()
456 u16 *buf = (u16 *)(par->info->screen_buffer + index); in metronomefb_dpy_update_page()
457 u16 *img = (u16 *)(par->metromem_img + index); in metronomefb_dpy_update_page()
472 struct metronomefb_par *par = info->par; in metronomefb_dpy_deferred_io()
476 unsigned long pgoffset = pageref->offset >> PAGE_SHIFT; in metronomefb_dpy_deferred_io()
477 cksum = metronomefb_dpy_update_page(par, pageref->offset); in metronomefb_dpy_deferred_io()
478 par->metromem_img_csum -= par->csum_table[pgoffset]; in metronomefb_dpy_deferred_io()
479 par->csum_table[pgoffset] = cksum; in metronomefb_dpy_deferred_io()
480 par->metromem_img_csum += cksum; in metronomefb_dpy_deferred_io()
488 struct metronomefb_par *par = info->par; in metronomefb_defio_damage_range()
496 struct metronomefb_par *par = info->par; in metronomefb_defio_damage_area()
520 int retval = -ENOMEM; in metronomefb_probe()
531 board = dev->dev.platform_data; in metronomefb_probe()
533 return -EINVAL; in metronomefb_probe()
536 if (!try_module_get(board->owner)) in metronomefb_probe()
537 return -ENODEV; in metronomefb_probe()
539 info = framebuffer_alloc(sizeof(struct metronomefb_par), &dev->dev); in metronomefb_probe()
544 info->screen_buffer which is vm, and is the fb used by apps. in metronomefb_probe()
545 par->metromem which is physically contiguous memory and in metronomefb_probe()
552 panel_type = board->get_panel_type(); in metronomefb_probe()
564 dev_err(&dev->dev, "Unexpected panel type. Defaulting to 6\n"); in metronomefb_probe()
579 info->screen_buffer = videomemory; in metronomefb_probe()
580 info->fbops = &metronomefb_ops; in metronomefb_probe()
587 info->var = metronomefb_var; in metronomefb_probe()
588 info->fix = metronomefb_fix; in metronomefb_probe()
589 info->fix.smem_len = videomemorysize; in metronomefb_probe()
590 par = info->par; in metronomefb_probe()
591 par->info = info; in metronomefb_probe()
592 par->board = board; in metronomefb_probe()
593 par->dt = epd_dt_index; in metronomefb_probe()
594 init_waitqueue_head(&par->waitq); in metronomefb_probe()
597 par->csum_table = vmalloc(videomemorysize/PAGE_SIZE); in metronomefb_probe()
598 if (!par->csum_table) in metronomefb_probe()
604 retval = board->setup_fb(par); in metronomefb_probe()
606 dev_err(&dev->dev, "Failed to setup fb\n"); in metronomefb_probe()
611 if ((!par->metromem_wfm) || (!par->metromem_img) || in metronomefb_probe()
612 (!par->metromem_dma)) { in metronomefb_probe()
613 dev_err(&dev->dev, "fb access failure\n"); in metronomefb_probe()
614 retval = -EINVAL; in metronomefb_probe()
618 info->fix.smem_start = par->metromem_dma; in metronomefb_probe()
623 retval = request_firmware(&fw_entry, "metronome.wbf", &dev->dev); in metronomefb_probe()
625 dev_err(&dev->dev, "Failed to get waveform\n"); in metronomefb_probe()
629 retval = load_waveform((u8 *) fw_entry->data, fw_entry->size, 3, 31, in metronomefb_probe()
633 dev_err(&dev->dev, "Failed processing waveform\n"); in metronomefb_probe()
637 retval = board->setup_irq(info); in metronomefb_probe()
645 info->flags = FBINFO_VIRTFB; in metronomefb_probe()
647 info->fbdefio = &metronomefb_defio; in metronomefb_probe()
650 retval = fb_alloc_cmap(&info->cmap, 8, 0); in metronomefb_probe()
652 dev_err(&dev->dev, "Failed to allocate colormap\n"); in metronomefb_probe()
658 info->cmap.red[i] = (((2*i)+1)*(0xFFFF))/16; in metronomefb_probe()
659 memcpy(info->cmap.green, info->cmap.red, sizeof(u16)*8); in metronomefb_probe()
660 memcpy(info->cmap.blue, info->cmap.red, sizeof(u16)*8); in metronomefb_probe()
668 dev_dbg(&dev->dev, in metronomefb_probe()
669 "fb%d: Metronome frame buffer device, using %dK of video" in metronomefb_probe()
670 " memory\n", info->node, videomemorysize >> 10); in metronomefb_probe()
675 fb_dealloc_cmap(&info->cmap); in metronomefb_probe()
677 board->cleanup(par); in metronomefb_probe()
679 vfree(par->csum_table); in metronomefb_probe()
685 module_put(board->owner); in metronomefb_probe()
694 struct metronomefb_par *par = info->par; in metronomefb_remove()
698 fb_dealloc_cmap(&info->cmap); in metronomefb_remove()
699 par->board->cleanup(par); in metronomefb_remove()
700 vfree(par->csum_table); in metronomefb_remove()
701 vfree(info->screen_buffer); in metronomefb_remove()
702 module_put(par->board->owner); in metronomefb_remove()
703 dev_dbg(&dev->dev, "calling release\n"); in metronomefb_remove()