⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 camif_fsm.c

📁 it s a source code for how to integrate your tvp5150 decoder with driver and how to capture an image
💻 C
字号:
/*      Copyright (C) 2004 Samsung Electronics                      SW.LEE <hitchcar@sec.samsung.com>    This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.*/#include <linux/version.h>#include <linux/module.h>#include <linux/delay.h>#include <linux/errno.h>#include <linux/fs.h>#include <linux/kernel.h>#include <linux/major.h>#include <linux/slab.h>#include <linux/poll.h>#include <linux/signal.h>#include <linux/ioport.h>#include <linux/sched.h>#include <linux/types.h>#include <linux/interrupt.h>#include <linux/kmod.h>#include <linux/vmalloc.h>#include <linux/init.h>#include <linux/pagemap.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/semaphore.h>#include <linux/miscdevice.h>//#define SW_DEBUG #include "heliosCam.h"	// by lovejin#include "camif.h"const char *fsm_version =        "$Id: camif_fsm.c,v 1.3 2004/04/27 10:26:28 swlee Exp $";/*  * FSM function is the place where Synchronization in not necessary * because IRS calls this functions. */ssize_t camif_p_1fsm_start(camif_cfg_t *cfg){	DEBUG0("[ %s() S ]\n",__FUNCTION__); // lovejin    //camif_reset(CAMIF_RESET,0);    cfg->exec = CAMIF_DMA_ON;    camif_capture_start(cfg);    camif_last_irq_en(cfg);    cfg->status = CAMIF_STARTED;    cfg->fsm = CAMIF_1nd_INT;	DEBUG0("[ %s() E ]\n",__FUNCTION__); // lovejin    return 0;}ssize_t camif_p_2fsm_start(camif_cfg_t *cfg){	DEBUG0("[ %s() S ]\n",__FUNCTION__); // lovejin    camif_reset(CAMIF_RESET,0);/* FIFO Count goes to zero */    cfg->exec = CAMIF_DMA_ON;    camif_capture_start(cfg);    cfg->status = CAMIF_STARTED;    cfg->fsm = CAMIF_1nd_INT;	DEBUG0("[ %s() E ]\n",__FUNCTION__); // lovejin    return 0;}ssize_t camif_4fsm_start(camif_cfg_t *cfg){	DEBUG0("[ %s() S ]\n",__FUNCTION__); // lovejin    camif_reset(CAMIF_RESET,0); /* FIFO Count goes to zero */    cfg->exec = CAMIF_DMA_ON;    camif_capture_start(cfg);    cfg->status = CAMIF_STARTED;    cfg->fsm = CAMIF_1nd_INT;    cfg->perf.frames = 0;	DEBUG0("[ %s() E ]\n",__FUNCTION__); // lovejin    return 0;}/* Policy:       cfg->perf.frames  set in camif_fsm.c     cfg->status set in video-driver.c *//*  * Don't insert camif_reset(CAM_RESET, 0 ) into this func  */ssize_t camif_p_stop(camif_cfg_t *cfg){	DEBUG0("[ %s() S ]\n",__FUNCTION__); // lovejin    cfg->exec = CAMIF_DMA_OFF;//  cfg->status = CAMIF_STOPPED;    camif_capture_stop(cfg);    cfg->perf.frames = 0;   /* Dupplicated ? */	DEBUG0("[ %s() E ]\n",__FUNCTION__); // lovejin    return 0;}/* When C working, P asks C to play together *//* Only P must call this function */void camif_start_c_with_p (camif_cfg_t *cfg, camif_cfg_t *other){	DEBUG0("[ %s() S ]\n",__FUNCTION__); // lovejin//  cfg->gc->other = get_camif(CODEC_MINOR);    cfg->gc->other = other;    camif_start_p_with_c(cfg);	DEBUG0("[ %s() E ]\n",__FUNCTION__); // lovejin}static void camif_start_p_with_c(camif_cfg_t *cfg){    camif_cfg_t *other = (camif_cfg_t *)cfg->gc->other;		DEBUG0("[ %s() S ]\n",__FUNCTION__); // lovejin    /* Preview Stop */    cfg->exec = CAMIF_DMA_OFF;    camif_capture_stop(cfg);    /* Start P and C */    camif_reset(CAMIF_RESET, 0);    cfg->exec =CAMIF_BOTH_DMA_ON;    camif_capture_start(cfg);    cfg->fsm = CAMIF_1nd_INT; /* For Preview */    if(!other) panic("Unexpected Error \n");    other->fsm = CAMIF_1nd_INT; /* For Preview */		DEBUG0("[ %s() E ]\n",__FUNCTION__); // lovejin}static void camif_auto_restart(camif_cfg_t *cfg){   	DEBUG0("[ %s() S ]\n",__FUNCTION__); // lovejin//  if (cfg->dma_type & CAMIF_CODEC) return;    if (cfg->auto_restart)        camif_start_p_with_c(cfg);	DEBUG0("[ %s() E ]\n",__FUNCTION__); // lovejin}/* Supposed that PREVIEW already running  * request PREVIEW to start with Codec  */static int camif_check_global(camif_cfg_t *cfg){    int ret = 0;		DEBUG0("[ %s() S ]\n",__FUNCTION__); // lovejin         if (down_interruptible(&cfg->gc->lock))         return -ERESTARTSYS;    if ( cfg->gc->status & CWANT2START ) {        cfg->gc->status &= ~CWANT2START;        cfg->auto_restart = 1;        ret = 1;    }    else {        ret = 0; /* There is no codec */        cfg->auto_restart = 0; /* Duplicated ..Dummy */    }    up(&cfg->gc->lock);	DEBUG0("[ %s() E ]\n",__FUNCTION__); // lovejin    return ret;}/* *    1nd INT : Start Interrupt *    Xnd INT : enable Last IRQ : pingpong get the valid data *    Ynd INT : Stop Codec or Preview : pingpong get the valid data *    Znd INT : Last IRQ : valid data  */#define CHECK_FREQ 5int camif_enter_p_4fsm(camif_cfg_t *cfg){    int ret = 0;		DEBUG0("[ %s() S ]\n",__FUNCTION__); // lovejin    cfg->perf.frames++;    if (cfg->fsm == CAMIF_NORMAL_INT)    if (cfg->perf.frames % CHECK_FREQ == 0)         ret = camif_check_global(cfg);    if (ret > 0) cfg->fsm = CAMIF_Xnd_INT; /* Codec wait for Preview */        switch (cfg->fsm) {        case CAMIF_1nd_INT:           /* Start IRQ */            cfg->fsm = CAMIF_NORMAL_INT;            ret = INSTANT_SKIP;            DPRINTK(KERN_INFO "1nd INT \n");                break;        case CAMIF_NORMAL_INT:                  cfg->status = CAMIF_INT_HAPPEN;            cfg->fsm = CAMIF_NORMAL_INT;            ret = INSTANT_GO;            DPRINTK(KERN_INFO "NORMAL INT \n");             break;        case CAMIF_Xnd_INT:                 camif_last_irq_en(cfg);/* IRQ for Enabling LAST IRQ */            cfg->status = CAMIF_INT_HAPPEN;            cfg->fsm = CAMIF_Ynd_INT;            ret = INSTANT_GO;            DPRINTK(KERN_INFO "Xnd INT \n");                break;          case CAMIF_Ynd_INT:        /* Capture Stop */            cfg->exec = CAMIF_DMA_OFF;            cfg->status = CAMIF_INT_HAPPEN;            camif_capture_stop(cfg);            cfg->fsm = CAMIF_Znd_INT;            ret = INSTANT_GO;            DPRINTK(KERN_INFO "Ynd INT \n");                break;        case CAMIF_Znd_INT:         /*  LAST IRQ (Dummy IRQ */            cfg->fsm = CAMIF_DUMMY_INT;            cfg->status = CAMIF_INT_HAPPEN;            ret = INSTANT_GO;            camif_auto_restart(cfg);  /* Automatically Restart Camera */            DPRINTK(KERN_INFO "Znd INT \n");            break;              case CAMIF_DUMMY_INT:            cfg->status = CAMIF_STOPPED; /* Dupplicate ? */            ret = INSTANT_SKIP;//          DPRINTK(KERN_INFO "Dummy INT \n");             break;        default:            printk(KERN_INFO "Unexpect INT %d \n",cfg->fsm);             ret = INSTANT_SKIP;            break;    }		DEBUG0("[ %s() E ]\n",__FUNCTION__); // lovejin    return ret;}/*  * NO autorestart included in this function  */int camif_enter_c_4fsm(camif_cfg_t *cfg){    int ret;		DEBUG0("[ %s() S ]\n",__FUNCTION__); // lovejin        cfg->perf.frames++;#if 0    if (   (cfg->fsm==CAMIF_NORMAL_INT)        && (cfg->perf.frames>cfg->restart_limit-1)       )         cfg->fsm = CAMIF_Xnd_INT;#endif    switch (cfg->fsm) {        case CAMIF_1nd_INT:           /* Start IRQ */            cfg->fsm = CAMIF_NORMAL_INT;//          cfg->status = CAMIF_STARTED; /* need this to meet auto-restart */            ret = INSTANT_SKIP;            DPRINTK(KERN_INFO "1nd INT \n");            break;        case CAMIF_NORMAL_INT:                  cfg->status = CAMIF_INT_HAPPEN;            cfg->fsm = CAMIF_NORMAL_INT;            ret = INSTANT_GO;            DPRINTK(KERN_INFO "NORMALd INT \n");            break;        case CAMIF_Xnd_INT:                 camif_last_irq_en(cfg);/* IRQ for Enabling LAST IRQ */            cfg->status = CAMIF_INT_HAPPEN;            cfg->fsm = CAMIF_Ynd_INT;            ret = INSTANT_GO;            DPRINTK(KERN_INFO "Xnd INT \n");            break;          case CAMIF_Ynd_INT:        /* Capture Stop */            cfg->exec = CAMIF_DMA_OFF;            cfg->status = CAMIF_INT_HAPPEN;            camif_capture_stop(cfg);            cfg->fsm = CAMIF_Znd_INT;            ret = INSTANT_GO;            DPRINTK(KERN_INFO "Ynd INT \n");            break;        case CAMIF_Znd_INT:         /*  LAST IRQ (Dummy IRQ */            cfg->fsm = CAMIF_DUMMY_INT;            cfg->status = CAMIF_INT_HAPPEN;            ret = INSTANT_GO;            DPRINTK(KERN_INFO "Znd INT \n");            break;              case CAMIF_DUMMY_INT:            cfg->status = CAMIF_STOPPED; /* Dupplicate ? */            ret = INSTANT_SKIP;            break;        default:            printk(KERN_INFO "Unexpect INT %d \n",cfg->fsm);             ret = INSTANT_SKIP;            break;    }		DEBUG0("[ %s() E ]\n",__FUNCTION__); // lovejin    return ret;}/* 4 Interrups State Machine is for two pingpong   *    1nd INT : Start Interrupt *    Xnd INT : enable Last IRQ : pingpong get the valid data *    Ynd INT : Stop Codec or Preview : pingpong get the valid data *    Znd INT : Last IRQ : valid data  *     * Note: *    Before calling this func, you must call camif_reset */int camif_enter_2fsm(camif_cfg_t *cfg) /* Codec FSM */{    int ret;		DEBUG0("[ %s() S ]\n",__FUNCTION__); // lovejin    cfg->perf.frames++;    switch (cfg->fsm) {        case CAMIF_1nd_INT:           /* Start IRQ */            cfg->fsm = CAMIF_Xnd_INT;            ret = INSTANT_SKIP;//          printk(KERN_INFO "1nd INT \n");             break;        case CAMIF_Xnd_INT:                 camif_last_irq_en(cfg);/* IRQ for Enabling LAST IRQ */            cfg->now_frame_num = 0;            cfg->status = CAMIF_INT_HAPPEN;            cfg->fsm = CAMIF_Ynd_INT;            ret = INSTANT_GO;//          printk(KERN_INFO "2nd INT \n");             break;          case CAMIF_Ynd_INT:        /* Capture Stop */            cfg->exec = CAMIF_DMA_OFF;            cfg->now_frame_num = 1;            cfg->status = CAMIF_INT_HAPPEN;            camif_capture_stop(cfg);            cfg->fsm = CAMIF_Znd_INT;            ret = INSTANT_GO;//          printk(KERN_INFO "Ynd INT \n");             break;        case CAMIF_Znd_INT:         /*  LAST IRQ (Dummy IRQ */            cfg->now_frame_num = 0;//          cfg->fsm = CAMIF_DUMMY_INT;            cfg->status = CAMIF_INT_HAPPEN;            ret = INSTANT_GO;//          printk(KERN_INFO "Znd INT \n");            break;              case CAMIF_DUMMY_INT:            cfg->status = CAMIF_STOPPED; /* Dupplicate ? */            ret = INSTANT_SKIP;            printk(KERN_INFO "Dummy INT \n");             break;        default:  /* CAMIF_PENDING_INT */            printk(KERN_INFO "Unexpect INT \n");             ret = INSTANT_SKIP;            break;    }		DEBUG0("[ %s() E ]\n",__FUNCTION__); // lovejin    return ret;}/* 2 Interrups State Machine is for one pingpong   *    1nd INT : Stop Codec or Preview : pingpong get the valid data *    2nd INT : Last IRQ : dummy data  */int camif_enter_1fsm(camif_cfg_t *cfg) /* Codec FSM */{    int ret;		DEBUG0("[ %s() S ]\n",__FUNCTION__); // lovejin    cfg->perf.frames++;    switch (cfg->fsm) {        case CAMIF_Ynd_INT:     /* IRQ for Enabling LAST IRQ */            cfg->exec = CAMIF_DMA_OFF;            camif_capture_stop(cfg);            cfg->fsm = CAMIF_Znd_INT;            ret = INSTANT_SKIP;    //      printk(KERN_INFO "Ynd INT \n");             break;          case CAMIF_Znd_INT:         /*  LAST IRQ (Dummy IRQ */            cfg->fsm = CAMIF_DUMMY_INT;            cfg->status = CAMIF_INT_HAPPEN;            ret = INSTANT_GO;    //      printk(KERN_INFO "Znd INT \n");             break;            case CAMIF_DUMMY_INT:            cfg->status = CAMIF_STOPPED; /* Dupplicate ? */            ret = INSTANT_SKIP;            printk(KERN_INFO "Dummy INT \n");             break;        default:            printk(KERN_INFO "Unexpect INT \n");             ret = INSTANT_SKIP;            break;    }		DEBUG0("[ %s() E ]\n",__FUNCTION__); // lovejin    return ret;}/* *  GLOBAL STATUS CONTROL FUNCTION * *//* Supposed that PREVIEW already running  * request PREVIEW to start with Codec  */int camif_callback_start(camif_cfg_t *cfg){    int  doit = 1;	DEBUG0("[ %s() S ]\n",__FUNCTION__); // lovejin    while (doit) {        if (down_interruptible(&cfg->gc->lock)) {            return -ERESTARTSYS;        }        cfg->gc->status = CWANT2START;        cfg->gc->other = cfg;        up(&cfg->gc->lock);        doit = 0;    }		DEBUG0("[ %s() E ]\n",__FUNCTION__); // lovejin    return 0;}/* * Return status of Preview Machine  ret value :      0: Preview is not working      X: Codec must follow PREVIEW start*/int camif_check_preview(camif_cfg_t *cfg){    int ret = 0; 		DEBUG0("[ %s() S ]\n",__FUNCTION__); // lovejin        if (down_interruptible(&cfg->gc->lock)) {        ret = -ERESTARTSYS;        return ret;    }    if (cfg->gc->user == 1) ret = 0;    //   else if (cfg->gc->status & PNOTWORKING) ret = 0;    else ret = 1;    up(&cfg->gc->lock);		DEBUG0("[ %s() E ]\n",__FUNCTION__); // lovejin    return ret;}/* * Local variables: * c-basic-offset: 8 * End: */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -