S5pc110 LCD Driver Analysis (1 ))

Source: Internet
Author: User
S5pc110 LCD Driver Analysis (1) ()

// Set the register 0xf800_0130 (Video interrupt control 0 register) [16: 15] bits to 01 = vsync, which may be 00 = back porch, 10 = active
Int s3cfb_set_vsync_interrupt (struct s3cfb_global * Ctrl, int enable)

// Set the register 0xf800_0130 enable or disable to [12] and [0], respectively, indicating
// Intfrmen [12] specifies the video frame interrupt enable control bit.
// 0 = disables video frame interrupt
// 1 = enables video frame interrupt
// Note: this bit is meaningful when inten is high
// Inten [0] specifies the video interrupt enable control bit.
// 0 = disables video interrupt
// 1 = enables video interrupt
Int s3cfb_set_global_interrupt (struct s3cfb_global * Ctrl, int enable)

Static int s3cfb_init_global (void)
{
Fbdev-> output = output_rgb;
Fbdev-> rgb_mode = mode_rgb_p;

Fbdev-> wq_count = 0;
Init_waitqueue_head (& fbdev-> WQ );
Mutex_init (& fbdev-> lock );

S3cfb_set_output (fbdev );
// Set the [28:26] bit of the register 0xf800_0000, which indicates
// Determines the output format of Video Controller.
// 000 = RGB interface
// 001 = Reserved
// 010 = indirect i80 interface for ldi0
// 011 = indirect i80 interface for ldi1
/// 100 = WB interface and RGB interface
/// 101 = Reserved
// 110 = WB interface and i80 interface for ldi0
// 111 = WB interface and i80 interface for ldi1
// Set the register 0xf800_0008 [] [] bits, meaning
// Reserved [15: 14] reserved.
// Note: This bit shocould be 1.
// Tvformatsel [13:12] specifies the output format of YUV data.
// 00 = Reserved
// 01 = yuv422
// 1X = yuv444
// Set all four digits to 0

S3cfb_set_display_mode (fbdev );
// Set the [18] [17] bits of the register 0xf800_0000. The meanings of the two are as follows:
// Rgspsel [18] selects display mode (vidout [1:0] = 2 'b00 ).
// 0 = RGB parallel format
// 1 = RGB serial format
// Selects the display mode (vidout [1:0]! = 2 'b00 ).
// 0 = RGB parallel format
// Pnrmode [17] controls inverting rgb_order (@ vidcon3 ).
// 0 = normal: rgborder [2] @ vidcon3
// 1 = invert :~ Rgborder [2] @ vidcon3
// Note: this bit is used for the previous version of fimd. You do
// Not have to use this bit if you use rgb_order @ vidcon3
// Register.
// This is set to 0 mode_rgb_p = 0,
Mode_bgr_p = 1,
Mode_rgb_s = 2,
Mode_bgr_s = 3,

S3cfb_set_polarity (fbdev );
// Set the register xf800_0004, which is in the [7], [6], [5], and [4] bits.
// Ivclk [7] controls the polarity of the vclk active edge.
// 0 = video data is fetched at vclk falling edge
// 1 = video data is fetched at vclk rising edge

// Ihsync [6] specifies the hsync pulse polarity.
// 0 = normal
// 1 = inverted

// Ivsync [5] specifies the vsync pulse polarity.
// 0 = normal
// 1 = inverted

// Ivden [4] specifies the vden signal polarity.
// 0 = normal
// 1 = inverted

S3cfb_set_timing (fbdev );
// Set the 32-bit 0xf800_0010 register to indicate
// Vbpvdf [31: 24] vertical back porch specifies the number of inactive lines at
// Start of a frame after vertical synchronization period. (Only for even
// Field of yvu Interface
// Vbpd [23: 16] vertical back porch specifies the number of inactive lines at
// Start of a frame after vertical synchronization period.
// Vfpd [15: 8] vertical front porch specifies the number of inactive lines at the end
// Of a frame before vertical synchronization period.
// Vspw [7:0] vertical sync pulse width determines the High-Level Width of vsync
// Pulse by counting the number of inactive lines.

// Set the register 0xf800_0014, which is expressed by 32 bits.
// Vfpvdf [31: 24] vertical front porch specifies the number of inactive lines at the end
// Of a frame before vertical synchronization period. (only for the even
// Field of yvu interface ).

// Hbpd [23: 16] horizontal back porch specifies the number of vclk periods
// Between the falling edge of hsync and start of active data.

// Hfpd [15: 8] horizontal front porch specifies the number of vclk periods
// Between the end of Active Data and rising edge of hsync.

// Hspw [7:0] horizontal sync pulse width determines the High-Level Width
// Hsync pulse by counting the number of vclk.

S3cfb_set_ LCD _size (fbdev );
// Set the register 0xf800_0018, which is expressed by the 22-bit valid bits.
// Lineval [21:11] determines the vertical size of display. In the interlace mode,
// (Lineval + 1) shocould be even.

// Hozval [10: 0] determines the horizontal size of display.
// Note: hozval = (horizontal display size)-1 and lineval = (vertical display size)-1.

Return 0;
}

Let's continue to look at the probe function.

/////////////////////////////////////////

Lcddebug ("% s, s3cfb init Global \ n", _ FUNC __);
S3cfb_init_global ();
Lcddebug ("% s, s3cfb init global done \ n", _ FUNC __);

# If! Defined (config_fb_89c_dummylcd)
S3cfb_display_on (fbdev );
// Set the [1] [0] of the register 0xf800_0000 to, which respectively represent
// ENVID [1] enables/disables video output and logic immediately.
// 0 = disables the video output and display control signal.
// 1 = enables the video output and display control signal
// Envid_f [0] enables/disables video output and logic at current frame end.
// 0 = disables the video output and display control signal.
// 1 = enables the video output and display control signal.
// * If this bit is set to "on" and "off", then "H" is read and video
// Controller is enabled until the end of current frame.
// Set the two to 1
# Endif

/* Panel control */
# If defined (FIG)
If (pdata-> backlight_on)
Pdata-> backlight_on (pdev );
# Elif defined (config_fb_initi_lte480wv)
Lcddebug ("% s, pdata-> backlight_onoff: % P \ n", _ FUNC __, pdata-> backlight_onoff );
// If conditions are met, call lte480wv_backlight_onoff to enable the backlight.
If (pdata-> backlight_onoff)
Pdata-> backlight_onoff (pdev, 1 );
# Endif

# If! Defined (config_fb_89c_dummylcd)
Lcddebug ("% s, pdata-> reset_ LCD: % P \ n", _ FUNC __, pdata-> reset_ LCD );
// If conditions are met, call the lte480wv_reset_ LCD function. The gph0_6 pin is the reset pin of the LCD.
// We can see that in the lte480wv_reset_ LCD function, gpio_request is called first. The first parameter is used to pass the macro s5pc11x_gph0 (6), and this parameter is used to directly index a static array.
// Static struct gpio_desc [arch_nr_gpios] Find the struct gpio_chip Member Address of the corresponding gpio_desc element in the array to determine whether it is a function pointer
// Chip-> whether the request is null. If yes, call this function. In our platform, this function does not exist. The second parameter is the label value. If the kernel option config_debug_fs
// If it is true, the struct gpio_desc contains the member label. You need to assign parameter 2 to it, and vice versa.
//
// Call gpio_direction_output (unsigned gpio, int value). Similarly, use the s5pc11x_gph0 (6) parameter to locate the corresponding struct gpio_chip and determine the Member.
// Whether the direction_output function pointer is null. If it is not null, status = chip-> direction_output (chip, gpio, value) is called. The function is actually called.
// Gpio_direction_output (s5pc11x_gph0 (6), 1), set the pin s5pc11x_gph0 (6) (e020_0c00) to output, and output DAT to 1
// Mdelay (10); delay: 10 ms
// Call the function gpio_set_value (s5pc11x_gph0 (6), 0)
# Define gpio_set_value _ gpio_set_value
_ Gpio_set_value (unsigned gpio, int value) // driver/gpio/gpiolib. c
Find the corresponding struct gpio_chip through the first parameter s5pc11x_gph0 (6)
Call the struct Member, function pointer void (* Set) (struct gpio_chip * chip,
Unsigned offset, int value );
Set points to the function initi_gpiolib_set. This function is located in/ARCH/ARM/plat-s3c/pgio. C.
The data register written to gph0 (6) In this function is 0.
// From this we can see that a low level is sent to gph0 (6 ).
// Mdelay (10)
// Call the function gpio_set_value (s5pc11x_gph0 (6), 1) at a high level
// Mdelay (10)
// Gpio_free (s5pc11x_gph0 (6); release this pin

If (pdata-> reset_ LCD)
Pdata-> reset_ LCD (pdev );
# Endif

Lcddebug ("% s, fbdev LCD init LDI: % P \ n", _ FUNC __, fbdev-> LCD-> init_ldi );
If (fbdev-> LCD-> init_ldi)
Fbdev-> LCD-> init_ldi ();

///////////////////////////////////

We continue to return to the main program to view the probe function.

///////////////////////////////

/* Prepare memory */
Lcddebug ("% s, s3cfb_alloc_framebuffer \ n" ,__ func __);
If (s3cfb_alloc_framebuffer ())
Goto err_alloc;
*************************************
Static int s3cfb_alloc_framebuffer (void) Analysis
Struct initi_platform_fb * pdata = to_fb_plat (fbdev-> Dev );
Int ret, I;

/* Alloc for framebuffers */
Fbdev-> Fb = (struct fb_info **) kmalloc (pdata-> nr_wins *\
Sizeof (struct fb_info *), gfp_kernel );
// Allocate the space of the FB Member of the Global struct s3cfb_global fbdev according to the number of windows set by the platform data. The Fb type is struct fb_info **
// The second-level pointer space is allocated here.
If (! Fbdev-> FB) {// handle errors
Err ("not enough memory \ n ");
Ret =-enomem;
Goto err_alloc;
}
/* Alloc for each framebuffer */
// Use the pdata-> nr_wins value to control the external loop. The value is 5.
For (I = 0; I <pdata-> nr_wins; I ++ ){
Fbdev-> FB [I] = framebuffer_alloc (sizeof (struct s3cfb_window ),\
Fbdev-> Dev );
// The type of fbdev-> FB [I] Is struct fb_info *. Call the framebuffer_alloc function to obtain the starting address of the allocated struct fb_info space.
// Framebuffer_alloc Function Analysis
* Framebuffer_alloc-creates a new frame buffer INFO structure
*
* @ Size: size of driver private data, can be zero
* @ Dev: pointer to the device for this FB, this can be null
*
* Creates a new frame buffer INFO structure. Also reserves @ size bytes
* For Driver private data (Info-> par). Info-> PAR (if any) will be
* Aligned to sizeof (long ).
*
* Returns the new structure, or null if an error occured.
Here sizeof (struct s3cfb_window) = 136 sizeof (struct fb_info) = 596
A total of 136 + 596 bytes of memory space is allocated. Info-> par points to the drive private data struct s3cfb_window

If (! Fbdev-> FB [I]) {// if the space allocation fails
Err ("not enough memory \ n ");
Ret =-enomem;
Goto err_alloc_fb;
}

Ret = s3cfb_init_fbinfo (I); // initialize the corresponding struct fb_info
If (RET ){
Err ("failed to allocate memory for FB % d \ n", I );
Ret =-enomem;
Goto err_alloc_fb;
}

If (I = pdata-> default_win ){
If (s3cfb_map_video_memory (fbdev-> FB [I]) {
Err ("failed to map video memory "\
"For default window (% d) \ n", I );
Ret =-enomem;
Goto err_alloc_fb;
} // Here, the default win is 0, so you need to map the first win memory space to the kernel virtual address space.
}
}

*************************************
Lcddebug ("% s, s3cfb_alloc_framebuffer done \ n" ,__ func __);

If (s3cfb_register_framebuffer ())
Goto err_alloc;

****************************************
Next, let's look at the s3cfb_register_framebuffer function. This function is mainly used to register five windows by calling register_framebuffer.
Macro defines config_framebuffer_console as true. This configuration item is in the kconfig file of the kernel
Config framebuffer_console
Tristate "framebuffer console support"
Depends on FB
Select CRC32
Help
Low-level framebuffer-based console driver.
The konfig file is located in/Drivers/Video/console/kconfig.

Int s3cfb_register_framebuffer (void)
{
Struct initi_platform_fb * pdata = to_fb_plat (fbdev-> Dev );
Int ret, I;

For (I = 0; I <pdata-> nr_wins; I ++ ){
Ret = register_framebuffer (fbdev-> FB [I]);
If (RET ){
Err ("failed to register framebuffer device \ n ");
Return-einval;
}

# Ifndef config_framebuffer_console
If (I = pdata-> default_win ){
S3cfb_check_var (& fbdev-> FB [I]-> var, fbdev-> FB [I]);
S3cfb_set_par (fbdev-> FB [I]);
S3cfb_draw_logo (fbdev-> FB [I]);
}
# Endif
}

Return 0;
}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.